La razón para Pasar un Puntero por Referencia en C++?

Las circunstancias en que se desea utilizar el código de esta naturaleza en c++?

void foo(type *&in) {...}

void fii() {
  type *choochoo;
  ...
  foo(choochoo);
}
  • si usted necesita devolver un puntero – mejor uso de un valor de retorno
  • Se puede exponer por qué? Este elogio no es muy útil. Mi pregunta es muy de fiar. Este es utilizado en la actualidad, el código de producción. Yo no entender del todo por qué.
  • David lo resume bastante bien. El puntero está siendo modificado.
  • Yo paso de esta manera si me va a llamar el operador «New» en la función.

6 Kommentare

  1. 131

    Usted quiere pasar un puntero por referencia, si usted tiene una necesidad de modificar el puntero en lugar de al objeto de que el puntero apunta.

    Esto es similar a ¿por qué el doble de punteros se utilizan; el uso de una referencia a un puntero es un poco más seguro que el uso de punteros.

    • De manera similar a un puntero de un puntero, a excepción de un menor nivel de direccionamiento indirecto para el paso por referencia semántica?
    • Ese es precisamente el de la derecha 🙂
    • Me gustaría añadir que, a veces, también desea devolver un puntero por referencia. Por ejemplo, si usted tiene una clase de la celebración de los datos en una asignación dinámica de la matriz, pero desea proporcionar (no constante) el acceso a estos datos para el cliente. Al mismo tiempo, usted no quiere que el cliente sea capaz de manipular la memoria a través del puntero.
    • ¿puede explicar eso? Suena muy interesante. Qué significa que el usuario de esa clase podría obtener un puntero a la interna del búfer de datos y lectura/escritura, pero no puede – por ejemplo – libre que búfer mediante delete o volver a enlazar ese puntero a algún otro lugar de la memoria? O yo me equivoco?
    • Seguro. Dicen que usted tiene una simple aplicación de una matriz dinámica. Naturalmente, usted va a sobrecargar el [] operador. Una posible (y de hecho natural) de la firma de este sería const T &operator[](size_t index) const. Pero usted también podría tener T &operator[](size_t index). Usted podría tener los dos al mismo tiempo. El último le permiten hacer cosas como myArray[jj] = 42. Al mismo tiempo, usted no está proporcionando un puntero a los datos, por lo que la persona que llama no puede meterse con la memoria (por ejemplo, eliminar accidentalmente).
    • Oh. Pensé que estaban hablando de devolver una referencia a un puntero (sus palabras exactas: «devolver un puntero por referencia», porque eso era lo OP que preguntó: pasar punteros por referencias, no simplemente de referencias) como una forma elegante de dar acceso de lectura/escritura para el búfer sin permitir manipular el búfer en sí (por ejemplo, la libera). La devolución de un antiguo llano de referencia es una cosa diferente y yo lo sé.
    • usted necesita para modificar el puntero en vez de the object... ¿digo esto sólo debe ser usado para modificar el puntero, y no debe ser utilizado para modificar el objeto señalado?

  2. 62

    50% de los programadores de C++ como para establecer sus punteros a null después de una eliminación:

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

    Sin la referencia, que sólo sería cambiar una copia local de el puntero, que no afecten a la persona que llama.

    • Me gusta el nombre ; )
    • En este ejemplo se hizo claro.para entender.
    • Voy a el comercio que suena estúpido para averiguar la respuesta: ¿por qué se llama idiotas eliminar? Lo que me estoy perdiendo?
    • Si nos fijamos en la historia, de la plantilla de función que solía ser llamado paranoid_delete, pero el Cachorro se renombró a moronic_delete. Él probablemente pertenece a el otro 50% 😉 de todos Modos, la respuesta corta es que la configuración de punteros a null después de delete casi nunca es útil (ya que debería ir fuera de alcance, de todos modos) y a menudo dificulta la detección de «utilizar después de» bichos».
    • Entiendo tu respuesta, pero @Cachorro parece pensar delete es estúpido en general. Cachorro, me hizo buscar un poco en google, no veo por qué eliminar es completamente inútil (tal vez soy un terrible googler también ;)). Puede explicar un poco más o proporcionar un enlace?
  3. 14

    David la respuesta es correcta, pero si todavía es un poco abstracto, aquí hay dos ejemplos:

    1. Usted podría querer poner a cero todos los liberados punteros para atrapar a los problemas de la memoria anterior. C-estilo te gustaría hacer:

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

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

      template<class T> void freeAndZero(T* &ptr)
      {
          delete ptr;
          ptr = 0;
      }
      
      int* ptr = new int;
      
      ...
      
      freeAndZero(ptr);
    2. Cuando se trata de con-listas – a menudo se representa como punteros a un siguiente nodo:

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

      En este caso, cuando se inserte a la lista vacía, necesariamente debe cambiar el entrante puntero porque el resultado no es el NULL puntero más. Este es un caso donde modificar un puntero externo de una función, de modo que hubiera una referencia a puntero en su firma:

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

    Hay un ejemplo en esta pregunta.

  4. 7

    He tenido que utilizar un código como este para proporcionar funciones para asignar memoria a un puntero pasado y volver a su tamaño, ya que mi empresa «objeto» para mí el uso de la STL

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

    No es agradable, pero el puntero debe ser pasado por referencia (o doble uso del puntero). Si no, la memoria se asigna a una copia local del puntero si se pasa por valor, lo que resulta en una pérdida de memoria.

  5. 2

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

    En general, se utilizan referencias a sugerencias si quieres pasar un puntero a una función y dejar que se mueva que original puntero a otra posición en lugar de solo mover una copia de la misma, sin afectar el original.

    • ¿Por qué el downvote? ¿Hay algo de malo con lo que escribí? Cuidado de explicar? 😛
  6. 0

    Otra situación en la que usted puede necesitar esto es, si usted tiene stl colección de punteros y desea cambiar
    ellos utilizando stl algoritmo. Ejemplo de for_each en c++98.

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

    De lo contrario, si el uso de changeObject(Objeto* elemento) firma tiene copia de puntero, no el original.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea