¿Motivo para pasar un puntero por referencia en C ++?

¿Bajo qué circunstancias querría usar código de esta naturaleza en c ++?

void foo(type *&in) {...} void fii() { type *choochoo; ... foo(choochoo); } 

Le conviene pasar un puntero por referencia si necesita modificar el puntero en lugar del objeto al que apunta el puntero.

Esto es similar a por qué se usan punteros dobles; usar una referencia a un puntero es ligeramente más seguro que usar punteros.

Al 50% de los progtwigdores de C ++ les gusta poner sus punteros a nulo después de una eliminación:

 template void moronic_delete(T*& p) { delete p; p = nullptr; } 

Sin la referencia, solo estaría cambiando una copia local del puntero, sin afectar a la persona que llama.

La respuesta de David es correcta, pero si todavía es un poco abstracta, aquí hay dos ejemplos:

  1. Es posible que desee poner a cero todos los punteros liberados para detectar problemas de memoria antes. Estilo C que harías:

     void freeAndZero(void** ptr) { free(*ptr); *ptr = 0; } void* ptr = malloc(...); ... freeAndZero(&ptr); 

    En C ++ para hacer lo mismo, puede hacer:

     template void freeAndZero(T* &ptr) { delete ptr; ptr = 0; } int* ptr = new int; ... freeAndZero(ptr); 
  2. Cuando se trata de listas enlazadas, a menudo simplemente representadas como punteros a un siguiente nodo:

     struct Node { value_t value; Node* next; }; 

    En este caso, cuando inserta en la lista vacía necesariamente debe cambiar el puntero entrante porque el resultado ya no es el puntero NULL . Este es un caso en el que modifica un puntero externo desde una función, por lo que tendría una referencia al puntero en su firma:

     void insert(Node* &list) { ... if(!list) list = new Node(...); ... } 

Hay un ejemplo en esta pregunta .

Tuve que usar código como este para proporcionar funciones para asignar memoria a un puntero pasado y devolver su tamaño porque mi empresa me “objeta” al usar el STL

  int iSizeOfArray(int* &piArray) { piArray = new int[iNumberOfElements]; ... return iNumberOfElements; } 

No es agradable, pero el puntero debe pasarse por referencia (o usar doble puntero). De lo contrario, la memoria se asigna a una copia local del puntero si se pasa por un valor que da como resultado una pérdida de memoria.

Un ejemplo es cuando escribe una función de analizador y le pasa un puntero de origen para leer, si se supone que la función debe empujar ese puntero hacia adelante detrás del último carácter que ha sido reconocido correctamente por el analizador. El uso de una referencia a un puntero deja claro entonces que la función moverá el puntero original para actualizar su posición.

En general, utiliza referencias a punteros si desea pasar un puntero a una función y dejar que mueva ese puntero original a alguna otra posición en lugar de mover una copia sin afectar el original.

Otra situación en la que puede necesitar esto es si tiene una colección stl de punteros y desea cambiarlos usando el algoritmo stl. Ejemplo de for_each en c ++ 98.

 struct Storage { typedef std::list ObjectList; ObjectList objects; void change() { typedef void (*ChangeFunctionType)(Object*&); std::for_each (objects.begin(), objects.end(), &Storage::changeObject); } static void changeObject(Object*& item) { delete item; item = 0; if (someCondition) item = new Object(); } }; 

De lo contrario, si usa la firma changeObject (Object * item) , tiene una copia del puntero, no del original.