sirven resueltos referencias que punteros puntero para los estructura ejercicios datos cadenas aritmetica apuntadores c++ memory pointers reference

resueltos - punteros y referencias c++



Diferencia entre el puntero a una referencia y referencia a un puntero (6)

¿Cuál es la diferencia entre un puntero a una referencia, una referencia a un puntero y un puntero a un puntero en C ++?

¿Dónde debería uno ser preferido sobre el otro?


Puntero a un puntero

Un puntero en C ++ es simplemente un valor que almacena una ubicación de memoria (generalmente como un valor de 32 bits).

Supongamos que tiene un valor entero de entrada de usuario ( 78 == 0x4E en hex).

Se almacenaría en la memoria de una manera similar a esto (estoy simplificando las cosas a propósito para este ejemplo):

Memory address Value 0x12345678 0x0000004E

Si quisiera crear un "puntero" a este valor, se vería así en la memoria:

Memory address Value 0x22334455 0x12345678

En la dirección de memoria 0x22334455 ahora tiene un "puntero" cuyo valor es 0x12345678 , o la dirección de memoria donde se almacena el valor entero de entrada del usuario ( 0x4E ).

Digamos que quería crear un "puntero" a este valor de puntero. Se vería así:

Memory address Value 0x11335577 0x22334455

Ahora tiene un nuevo valor de "puntero" en la memoria que almacena la dirección de memoria del valor del puntero previamente definido.

Los punteros se pueden crear así indefinidamente: la clave es recordar que un puntero es simplemente otro valor que el compilador interpreta como una ubicación de memoria (y proporciona varias semánticas de acceso como * y -> que son especiales para los tipos de "puntero").

Referencia a un puntero

Se puede considerar una referencia como una vista, o un alias, en otro objeto real. Cuando crea una referencia a un puntero llamado myReference , simplemente está definiendo un nuevo nombre llamado myReference que se puede usar para acceder al puntero que ha definido previamente en la memoria.

Internamente, las referencias se implementan usando punteros, pero esto está más allá del alcance de su pregunta.

Las referencias tienen restricciones sobre otros tipos en C ++; por ejemplo, siempre debe inicializar una referencia para "referir" a un objeto real cuando lo crea, mientras que un puntero puede apuntar a la memoria que no es válida o no está inicializada.

Puntero a una referencia

Esto no existe Como se dijo anteriormente, una referencia es simplemente un alias de otro objeto. No puede "apuntar" a una referencia, porque no es un objeto en sí mismo sino simplemente otro nombre para un objeto real.

Por supuesto, puede tener un puntero al objeto al que hace referencia una referencia. Pero ahora estamos de vuelta en el territorio puntero de vainilla.

Nota sobre los parámetros

Cuando pasa un parámetro por valor a un método o rutina, esencialmente está pasando una "copia" del objeto al método. Cualquier cambio que realice en el valor dentro de la rutina se perderá cuando regrese la rutina, ya que el parámetro se tratará como una variable local en el contexto de la rutina.

Si desea modificar un parámetro que se transfiere para que el código del cliente (llamada) pueda acceder al cambio, debe pasar el parámetro por puntero o por referencia .

Por ejemplo:

void myMethod(int myValue) { // NOTE: This change will be lost to the caller! myValue = 5; } void myMethod2(int* myValue) { // Correct way of modifying pointer parameter value *myValue = 5; } void myMethod3(int& myValue) { // Correct way of modifying reference parameter value myValue = 5; }

Digamos ahora que su método quiere asignar memoria para un puntero. Podrías sentirte tentado de hacer esto:

void myMethod4(int* myValue) { // Warning: You will lose the address of the allocated // memory when you return! myValue = new int[5]; }

Pero recuerde, usted está modificando la copia del valor del puntero aquí, no el valor real del puntero. Como quiere modificar el puntero en esta rutina y no el valor al que apunta el puntero, debe pasarlo como un "puntero a un puntero" o una "referencia a un puntero":

void myMethod5(int** myValue) { // Correct way of allocating memory in a method // via pointer-to-pointer *myValue = new int[5]; } void myMethod6(int*& myValue) { // Correct way of allocating memory in a method // via reference-to-pointer myValue = new int[5]; }

En estos 2 ejemplos de abajo, el código que llama a myMethod5 y myMethod6 obtendrá correctamente la dirección de memoria de la memoria recientemente asignada a través del puntero o referencia del parámetro myValue .


Es importante observar que aunque una referencia no es un objeto y, por lo tanto, no tiene una dirección accesible, una referencia puede estar contenida dentro de un objeto y el objeto que lo contiene tiene una dirección.

struct contains_ref { int& ref; contains_ref(int& target) : ref(target) {} };

La explicación de "referencia es un alias" no es incorrecta, pero a menudo va acompañada de afirmaciones engañosas. Una referencia no es equivalente al objeto original. Tiene su propia vida, determinada por el alcance u objeto que la contiene, y no por el objeto al que se refiere. Y una referencia puede sobrevivir a un objeto y usarse para referirse a un nuevo objeto creado en la misma dirección.

Trate una referencia como lo que realmente es: una abstracción alrededor de un puntero que excluye el valor nulo como válido, y evita que se vuelva a unir 1 , y no algo mágico. La única propiedad inusual de una referencia que no se deriva de su naturaleza de puntero es la extensión de por vida de los temporales.

1 En realidad, esto es una consecuencia del hecho de que C ++ no proporciona ninguna sintaxis para referirse a la referencia en sí misma en lugar de su objetivo. Todos los operadores, incluido el operador de asignación, simplemente se aplican al objetivo.


No existe un puntero a una referencia.


Primero, una referencia a un puntero es como una referencia a cualquier otra variable:

void fun(int*& ref_to_ptr) { ref_to_ptr = 0; // set the "passed" pointer to 0 // if the pointer is not passed by ref, // then only the copy(parameter) you received is set to 0, // but the original pointer(outside the function) is not affected. }

Un puntero a referencia es ilegal en C ++, porque -a diferencia de un puntero- una referencia es solo un concepto que permite al programador crear alias de otra cosa. Un puntero es un lugar en la memoria que tiene la dirección de otra cosa, pero una referencia NO.

Ahora el último punto podría no ser muy claro, si insistes en tratar las referencias como punteros. p.ej:

int x; int& rx = x; // from now on, rx is just like x. // Unlike pointers, refs are not real objects in memory. int* p = &x; // Ok int* pr = ℞ // OK! but remember that rx is just x! // i.e. rx is not something that exists alone, it has to refer to something else. if( p == pr ) // true! { ... }

Como puede ver en el código anterior, cuando usamos la referencia, no estamos tratando con algo separado de lo que se refiere. Entonces, la dirección de una referencia es solo la dirección a la que se refiere. Es por eso que no hay tal cosa llamada la dirección de la referencia en términos de lo que está hablando.


Solo trata de ver por ti mismo qué es lo que sostiene cada cosa. El programa de ejemplo simplemente imprime el valor para un int y las direcciones de diferentes entidades:

#include<stdio.h> int main(){ int myInt ; int *ptr_to_myInt = &myInt; int *ptr_to_myInt_ref = ptr_to_myInt; myInt = 42; printf("myInt is %d/n",myInt); printf("ptr_to_myInt is %x/n",ptr_to_myInt); printf("ptr_to_myInt_ref is %x/n",ptr_to_myInt_ref); printf("&ptr_to_myInt is %x/n",&ptr_to_myInt); return 0; }

Salida:

myInt is 42 ptr_to_myInt is bffff858 ptr_to_myInt_ref is bffff858 &ptr_to_myInt is bffff854

Entonces, el puntero al int y el puntero a la referencia del int son exactamente lo mismo. Esto es obvio desde el código, porque el puntero a una referencia es simplemente otra forma de aliasar un puntero (es decir "mantener la siguiente dirección para mí").

Ahora, el puntero también necesita espacio en la memoria, y si imprime la referencia a este puntero (la última instrucción printf) simplemente indica el lugar en la memoria donde reside el puntero.


Una referencia es una abstracción de punteros. Las referencias son un poco más difíciles de arruinar, especialmente para los principiantes, y son un poco más alto nivel.

No necesitas referencias Siempre puedes usar punteros. Sin embargo, a veces el código puede ser más fácil de leer con ellos.

Un ejemplo típico de principiante es una lista vinculada. Imagine que tiene una variable llamada "lista" que contiene un puntero al primero. Si quisiera agregar algo a la cabeza, debería darle a su add () un doble puntero, ya que necesita poder modificar "head". Sin embargo, puede usar una referencia a un puntero en su lugar. Aquí, queremos usar punteros en la lista en sí, ya que los mutaremos, pero la función add () será más clara si pasamos una referencia al encabezado de la lista en lugar de un puntero doble.

Simplemente son una elección de estilo. Si está trabajando en un proyecto más grande, debe seguir el estilo del proyecto. Si no, puedes usar lo que sientas que sea preferible. Sin embargo, deberías sentirte cómodo usando todos los estilos si esperas ser un programador C ++ medianamente exitoso.

También vale la pena que no puedas tener un puntero a una referencia. Esto se debe a que las referencias son realmente solo otro nombre para otra variable, que puede estar en algún otro ámbito. Tener un puntero a una referencia no tiene sentido. Lo que realmente desea es solo un indicador de los datos originales, sin referencias involucradas.