0% encontró este documento útil (0 votos)
4 vistas11 páginas

Ejemplos de Punteros en Java

El documento aborda la declaración e inicialización de variables y punteros en Java y C++, destacando la diferencia entre referencias y objetos, así como la importancia de la inicialización. Se explican los operadores de apuntador, su declaración y uso, así como las llamadas por valor y por referencia en C++, incluyendo ejemplos prácticos. Además, se discuten las ventajas y desventajas de ambos métodos de llamada en términos de eficiencia y manipulación de datos.

Cargado por

Fernando Jimenez
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
4 vistas11 páginas

Ejemplos de Punteros en Java

El documento aborda la declaración e inicialización de variables y punteros en Java y C++, destacando la diferencia entre referencias y objetos, así como la importancia de la inicialización. Se explican los operadores de apuntador, su declaración y uso, así como las llamadas por valor y por referencia en C++, incluyendo ejemplos prácticos. Además, se discuten las ventajas y desventajas de ambos métodos de llamada en términos de eficiencia y manipulación de datos.

Cargado por

Fernando Jimenez
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd

Tema: Punteros

1. Declaración e inicialización
1.1 Declaración [1]
Una declaración de variables se define especificando el tipo y el nombre de dicha variable. Estas
variables pueden ser tanto de tipos primitivos como referencias a objetos de alguna clase
perteneciente al API de Java o generada por el usuario. Si no se especifica un valor en su
declaración, las variables primitivas se inicializan a cero salvo boolean y char, que se inicializan a
false y '\0'.

Imagen 1. Imagen representativa de la declaración.

1.1.2 Objetos y referencias


Es importante distinguir entre la referencia a un objeto y el objeto mismo. Una referencia es una
variable que indica dónde está guardado un objeto en la memoria del ordenador a diferencia de
C/C++, Java no permite acceder al valor de la dirección, pues en este lenguaje se han eliminado los
punteros. Al declarar una referencia todavía no se encuentra “apuntando” a ningún objeto en
particular salvo que se cree explícitamente un nuevo objeto en la declaración, y por eso se le asigna
el valor null. Si se desea que esta referencia apunte a un nuevo objeto es necesario crear el objeto
utilizando el operador new. Este operador reserva en la memoria del ordenador espacio para ese
objeto sea declaracion de variables y funciones.
Las variables en los arrays
Un tipo particular de referencias son los arrays o vectores, sean éstos de variables primitivas como
por ejemplo, un vector de enteros o de objetos. En la declaración de una referencia de tipo array hay
que incluir los corchetes [1].

Imagen 2. Imagen representativa de la declaración


array.
1.1.3 Ejemplos de variables
Ejemplos de cómo declarar e inicializar variables:
int x; Declaración de la variable primitiva x. Se inicializa a 0
int y = 5; Declaración de la variable primitiva y. Se inicializa a 5
MiClase unaRef; Declaración de una referencia a un objeto MiClase.
unaRef = new MiClase(); La referencia apunta al nuevo objeto creado utilizando el constructor por
defecto.
MiClase segundaRef = unaRef; Declaración de una referencia a un objeto MiClase.
int [] vector; Declaración de un array. Se inicializa a null.
vector = new int[10]; Vector de 10 enteros, inicializados a 0
double [] v = {1.0, 2.65, 3.1}; Declaración e inicialización de un vector de 3 elementos con los
valores entre llaves
MiClase [] lista=new MiClase [5]; Se crea un vector de 5 referencias a objetos las 5 referencias son
inicializadas a null.
lista[0] = unaRef; Se asigna a lista[0] el mismo valor que unaRef.
lista[1] = new MiClase (); Se asigna a lista[1] la referencia al nuevo objeto el resto lista[2]…lista[4]
siguen con valor null.
En el ejemplo mostrado las referencias unaRef, segundaRef y lista[0] actuarán sobre el mismo
objeto. Es equivalente utilizar cualquiera de las referencias ya que el objeto al que se refieren es el
mismo.[1]

1.2 Inicialización

Un "inicializador" es un valor o una secuencia de valores que se deben asignar a la variable que se
declara. Se puede establecer una variable en un valor inicial si se aplica un inicializador al
declarador en la declaración de variable. El valor o los valores del inicializador se asignan a la
variable.[2]
1.2.1 inicializar tipos escalares
Al inicializar tipos escalares, el valor de assignment-expression se asigna a la variable. Se aplican
las reglas de conversión de la asignación.

Sintaxis
declaration:
declaration-specifiersoptinit-declarator-list ;

declaration-specifiers:
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt

init-declarator-list:
init-declarator
init-declarator-list , init-declarator

init-declarator:
declarator
declarator = initializer /* Para la inicialización escalar */

initializer:
assignment-expression

Puede inicializar variables de cualquier tipo, siempre que observe las reglas siguientes:
 Las variables declaradas en el nivel de ámbito de archivo se pueden inicializar. Si no
inicializa explícitamente una variable en el nivel externo, se inicializa en 0 de forma
predeterminada.
 Una expresión constante se puede utilizar para inicializar una variable global declarada con
el especificador static storage-class-specifier. Las variables declaradas como static se
inicializan cuando comienza la ejecución del programa. Si no inicializa explícitamente una
variable global static, se inicializa en 0 de forma predeterminada y se asigna un puntero null
a cada miembro que tenga el tipo de puntero.
 Las variables declaradas con el especificador de clase de almacenamiento auto o register se
inicializan cada vez que el control en tiempo de ejecución pasa al bloque donde se declaran.
Si omite un inicializador en la declaración de una variable auto o register , el valor inicial
de la variable es indefinido. Para los valores auto y register, el inicializador no se limita a
una constante; puede ser cualquier expresión que contenga valores definidos previamente,
incluidas llamadas de función.
 Los valores iniciales de las declaraciones de variables externas y de todas las variables
static , tanto sin son externas como internas, deben ser expresiones constantes. (Para
obtener más información, vea Expresiones constantes). Como la dirección de cualquier
variable definida externamente o variable estática es constante, se puede utilizar para
inicializar una variable de puntero static declarada internamente. Sin embargo, la dirección
de una variable auto no puede utilizarse como inicializador estático porque puede ser
diferente en cada ejecución del bloque. Puede utilizar valores constantes o variables para
inicializar las variables auto o register.
Si la declaración de un identificador tiene ámbito de bloque y el identificador tiene vinculación
externa, la declaración no puede tener una inicialización.[3]
1.2.2. Inicializar cadenas
Puede inicializar una matriz de caracteres (o caracteres anchos) con un literal de cadena (o literal de
cadena ancho). Por ejemplo:
char code[ ] = "abc";
inicializa code como una matriz de caracteres de cuatro elementos. El cuarto elemento es el carácter
null, que finaliza todos los literales de cadena.
La longitud de una lista de identificadores solo puede equivaler al número de identificadores que se
inicializarán. Si especifica un tamaño de matriz que es más corto que la cadena, se omiten los
caracteres adicionales. Por ejemplo, la declaración siguiente inicializa code como una matriz de
caracteres de tres elementos:
char code[3] = "abcd";
Solo los tres primeros caracteres del inicializador se asignan a code. Se descartan el carácter d y el
carácter null que finaliza la cadena. Observe que se crea una cadena no finalizada (es decir, una
cadena que carece de un valor 0 que indique su final) y genera un mensaje de diagnóstico para
notificar esta condición.
La declaración
char s[] = "abc", t[3] = "abc";
es idéntica a
char s[] = {'a', 'b', 'c', '\0'},
t[3] = {'a', 'b', 'c' };
Si el tamaño de la cadena es menor que el especificado de la matriz, los elementos restantes de la
matriz se inicializan en 0.[4]
2. Operadores de apuntador
Cuando se declara una variable, el compilador reserva un espacio de memoria para ella y asocia el
nombre de está a la dirección de memoria desde donde comienzan los datos de esa variable. Las
direcciones de memoria se suelen describir como números en hexadecimal.
Un apuntador es una variable cuyo valor es la dirección de memoria de otra variable. Se dice que un
apuntador “apunta” a la variable cuyo valor se almacena a partir de la dirección de memoria que
contiene el apuntador. Por ejemplo, si un apuntador p almacena la dirección de una variable x, se
dice que “p apunta a x”.
2.1 Referenciación
La referenciación es la obtención de la dirección de una variable. En C y C++ esto se hace a través
del operador ‘&’, aplicado a la variable a la cual se desea saber su dirección. Nótese que se trata de
un operador unario. Ejemplo:
Código C y C++ int x = 25;
<< "La dirección de x es: " << &x << endl;
Este código imprime un valor del estilo “0x4fffd34”. Este valor puede variar durante cada ejecución
del programa, debido a que el programa puede reservar distintos espacios de memoria durante cada
ejecución.
2.2. Declaración de apuntadores
Para declarar un apuntador se especifica el tipo de dato al que apunta, el operador ‘*’, y el nombre
del apuntador. La sintaxis es la siguiente:
<tipo de dato apuntado> *<identificador del apuntador> A continuación, se muestran varios
ejemplos:
int *ptr1; Código // Apuntador a un dato de tipo entero (int)
char *cad1, *cad2; // Dos apuntadores a datos de tipo carácter (char)
float *ptr2; // Apuntador a un dato de tipo punto-flotante (float)
2.3 Asignación de apuntadores
Se pueden asignar a un apuntador direcciones de variables a través del operador de referenciación
(‘&’) o direcciones almacenadas en otros apuntadores. Ejemplo:
Código C y C++
int i = 5;
int *p, *q;
p = &i; // Se le asigna a ’p’ la dirección de ’i’
q = p; // Se le asigna a ’q’ la dirección almacenada en ’p’ (la misma de ’i’)
[5]
3. Uso de apuntadores
Llamados también punteros. Un Apuntador es una variable que contiene una dirección de memoria,
la cual corresponderá a un dato o a una variable que contiene el dato. Cada variable que se utiliza en
una aplicación ocupa una o varias posiciones de memoria. Estas posiciones de memoria se accesan
por medio de una dirección.
3.1 Operador de dirección y de indirección
El Operador de Dirección ( &) regresa la dirección de una variable.
El Operador de Indirección ( * ), toma la dirección de una variable y regresa el dato que contiene
esa dirección.
3.2 Sintaxis
La declaración de un puntero de manera general es:
Tipo dato *nombre de apuntador;
Tipo dato : Especifica el tipo de objeto apuntado y puede ser cualquier tipo (int, float, char, etc).
Nombre de apuntador: Es el identificador (nombre asignado) del apuntador.
Ejemplos de declaración:
int *ptr, cont;
float *res;
short *bandera;
char *mensaje;

4. Llamadas por valor y referencia


4.1 Llamada por valor en C++
En este método, el valor de actual parameterse pasa al valor correspondiente de la función llamada.
Esta técnica garantiza que los datos originales no sean alterados por la función llamada, ya que esta
solo procesa una copia de esos datos. formal parameteractual parameter
Cuando un programador opta por él , el espacio de memoria para él se asigna por separado en él , lo
que refuerza aún más el hecho de que los datos originales permanecen intactos. Por lo tanto, y se
asignan a diferentes ubicaciones de [Link] by valueformal parametersfunction stackformal
parametersactual parameters[5]
4.1.1 Cuando utilizar Llamada por valor en C++
 Cuando no desea cambiar los parámetros reales de la función.
 Cuando desea hacer copias de los datos en lugar de los datos reales.
 Cuando el espacio no es un problema.
 Por lo general, cuando no se trata de recursión o retroceso.[5]
4.1.2 Llamada por valor en C++ con ejemplo
#include <iostream>
using namespace std;
void swap(int x, int y) {
int temp = x;
x = y;
y = temp;
}
int main() {
int a = 40;
int b = 50;
cout << "Before swap: a = " << a << " b = " << b << endl;
swap(a, b);
cout << "After swap: a = " << a << " b = " << b << endl;
return 0;
}
El programa anterior, en el compilador de C++, intercambia los valores de las variables y. En la
función, pasa los valores de y a la función. La función intercambia los valores de y.
abmain()function callactual parameterabswap()swap()ab

Debido a este método, el valor de las variables originales permanece sin cambios incluso después
del intercambio por la funció[Link] by valueabswap()
4.1.3 Ventajas de usar llamadas por valor en C++
 Este método no modifica la variable original. Es decir, conserva los datos.
 Cada vez que se llama a una función, nunca afecta el contenido real de los argumentos
reales.
 Aquí, el valor de los argumentos reales se transfiere a los argumentos formales. Por lo
tanto, cualquier cambio en el argumento formal no afecta los casos reales.
4.1.4 Desventajas de usar llamadas por valor en C++
 Los datos transmitidos se almacenan en la memoria temporal.
 No se puede operar sobre los datos reales sino sobre una copia temporal de los datos,
por lo que los cambios realizados en los datos en la función no se reflejan en la función
main().
 El espacio de memoria requerido al utilizar cadenas , matrices , vectores, etc. puede ser
enorme.
 La solución del retroceso y la recursión puede ser compleja utilizando llamadas por
valor.
4.2 Llamada por referencia en C++
En este método, en lugar de pasar los valores de a los formales, se pasan las direcciones de. Por lo
tanto, la modificación de la función llamada a también afecta a. actual parametersactual
parametersformal parametersactual parameters
Cuando un programador opta por, el espacio de memoria para y es el mismo. Todas las operaciones
de la función se realizan sobre el valor almacenado en la dirección de, y el valor modificado se
almacena en la misma direcció[Link] by referenceformal parametersactual parametersactual
parameters.
Esta técnica no solo conserva la memoria, sino que también simplifica la colaboración, ya que los
tipos de datos complejos como o pueden manipularse fácilmente sin duplicarse
[Link].
4.2.1Cuando utilizar llamada por referencia en C++
 Cuando el programador quiere modificar el valor original de una variable dentro de una
función y tener esas modificaciones reflejadas en el código de llamada.
 Supongamos que tiene un objeto grande (por ejemplo, una estructura de datos compleja o
una instancia de clase) y desea evitar la sobrecarga de copiarlo.
 Cuando necesitas modificar los parámetros de la función en sí, en lugar de sólo los valores
que representan.
 Al trabajar con grandes cantidades de datos, dado que el paso por referencia no crea una
copia de los datos, aumenta la eficiencia.
4.2.2. Llamada por referencia en el compilador de C++ con ejemplo
#include <iostream>
using namespace std;
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 5;
int y = 10;
cout << "Before swap: x = " << x << " , y = " << y << endl;
swap(&x, &y);
cout << "After swap: x = " << x << ", y = " << y << endl;
return 0;
}
En el programa anterior de intercambio de dos números, la main()función pasa la dirección de las
dos variables y, como se indica mediante el operador de referencia. abactual parametersfunction call
&
La función usa el puntero para obtener el valor de las variables cuyas direcciones se pasan
mediante. Tras intercambiar los valores, el valor de se modifica permanentemente al pasarse la
dirección de las [Link]()function callactual parameters.
4.2.3 Ventajas de usar llamadas por referencia en C++
 La función puede cambiar el valor del argumento, lo cual resulta muy beneficioso.
 No crea datos duplicados para almacenar valores, lo que ayuda a ahorrar espacio en la
memoria.
 Ayuda a evitar cambios que ocurren por error.
 Una persona que lee el código no es consciente de que el valor se puede modificar en la
función.
4.2.4. Desventajas de usar llamadas por referencia en C++
 Una función que toma una referencia requiere asegurar que la entrada no sea nula. Por lo
tanto, no se debe realizar una comprobación de valores nulos. Por lo tanto, tiene una
garantía de valores no nulos.
 Pasar por referencia hace que la función no sea pura teóricamente
 Con las referencias, una garantía de por vida es un gran problema. Es especialmente
peligrosa al trabajar con lambdas y programas multihilo.[5]

También podría gustarte