Sé referencias azúcar sintáctico, así que el código es más fácil de leer y de escribir.

Pero ¿cuáles son las diferencias?


Resumen de las respuestas y enlaces a continuación:

  1. Un puntero puede ser re-asignar cualquier número de veces, mientras que una referencia no puede ser re-asignados después de la unión.
  2. Punteros pueden apuntar a ninguna parte (NULL), mientras que una referencia se refiere siempre a un objeto.
  3. Usted no puede tomar la dirección de una referencia de como se puede hacer con punteros.
  4. No hay ninguna «referencia de la aritmética» (pero usted puede tomar la dirección de un objeto apuntado por una referencia y hacer aritmética de punteros en él como en &obj + 5).

Para aclarar un concepto erróneo:

El estándar de C++ es muy cuidadoso para evitar el dictado de cómo un compilador puede
implementar referencias, pero cada compilador de C++ implementa
referencias como punteros. Es decir, una declaración como:

int &ri = i;

si no está optimizada del todo, asigna la misma cantidad de almacenamiento
como un puntero, y coloca la dirección
de i en ese almacenamiento.

Así, un puntero y de referencia tanto en el uso de la misma cantidad de memoria.

Como regla general,

  • Referencias de uso en función de los parámetros y tipos de retorno para proporcionar útiles y de auto-documentación de las interfaces.
  • Uso de punteros para la aplicación de algoritmos y estructuras de datos.

Lectura interesante:

Creo que el punto 2 debe ser «Un puntero se le permite ser NULO, sino una referencia que no es. Sólo incorrecto el código puede crear una referencia NULA y su comportamiento no está definido.»
Los punteros son sólo otro tipo de objeto, y como cualquier objeto en C++, que puede ser una variable. Referencias en el otro lado nunca son objetos, solo variables.
Esto compila sin advertencias: int &x = *(int*)0; en gcc. De referencia, de hecho pueden apuntar a NULL.
referencia es una variable alias
Me gusta cómo la primera frase es una total falacia. Las referencias tienen su propia semántica.

OriginalEl autor prakash | 2008-09-11

30 Comentarios

  1. 1446
    1. Un puntero puede ser re-asignados:

      int x = 5;
      int y = 6;
      int *p;
      p =  &x;
      p = &y;
      *p = 10;
      assert(x == 5);
      assert(y == 10);

      Una referencia no puede, y debe ser asignado en la inicialización:

      int x = 5;
      int y = 6;
      int &r = x;
    2. Un puntero tiene su propia dirección de memoria y el tamaño de la pila (4 bytes en x86), mientras que una referencia comparte la misma dirección de memoria (con la variable original), sino que también ocupa espacio en la pila. Desde una referencia a la misma dirección de la variable original en sí, es seguro que pensar en una referencia como otro nombre para la misma variable. Nota: Lo que es un puntero que señala a puede ser en la pila o montón. Ídem referencia. Mi reclamo en esta declaración no es que un puntero debe apuntar a la pila. Un puntero es simplemente una variable que contiene una dirección de memoria. Esta variable está en la pila. Desde una referencia tiene su propio espacio en la pila, y ya que la dirección es la misma que la variable que hace referencia. Más sobre pila vs montón. Esto implica que hay una dirección real de una referencia de que el compilador no te digo.

      int x = 0;
      int &r = x;
      int *p = &x;
      int *p2 = &r;
      assert(p == p2);
    3. Usted puede tener punteros a punteros a punteros ofreciendo nivel extra de indirección. Mientras que las referencias sólo ofrecen un nivel de indirección.

      int x = 0;
      int y = 0;
      int *p = &x;
      int *q = &y;
      int **pp = &p;
      pp = &q;//*pp = q
      **pp = 4;
      assert(y == 4);
      assert(x == 0);
    4. Puntero puede ser asignado nullptr directamente, mientras que la referencia no puede. Si te esmeras, y usted sabe, usted puede hacer la dirección de una referencia nullptr. Del mismo modo, si te esmeras usted puede tener una referencia a un puntero y, a continuación, que hacen referencia puede contener nullptr.

      int *p = nullptr;
      int &r = nullptr; <--- compiling error
      int &r = *p;  <--- likely no compiling error, especially if the nullptr is hidden behind a function call, yet it refers to a non-existent int at address 0
    5. Punteros puede iterar a través de una matriz, puede utilizar ++ para ir al siguiente elemento que un puntero que apunta, y + 4 para ir a la 5º elemento. Esto es, no importa el tamaño del objeto es la que señala el puntero.

    6. Un puntero tiene que ser sin referencia con * para acceder a la ubicación de memoria que señala, mientras que una referencia se puede utilizar directamente. Un puntero a una clase o struct utiliza -> para acceder a sus miembros, mientras que una referencia utiliza un ..

    7. Un puntero es una variable que contiene una dirección de memoria. Independientemente de cómo una referencia es implementado, una referencia a la misma dirección de memoria como el elemento que hace referencia.

    8. Referencias no pueden ser embutidos en una matriz, mientras que los punteros pueden (Mencionada por el usuario @litb)

    9. Const referencias puede ser obligado a temporales. Punteros no (no sin algunos direccionamiento indirecto):

      const int &x = int(12); //legal C++
      int *y = &int(12); //illegal to dereference a temporary.

      Esto hace que const& más seguro para su uso en las listas de argumentos y así sucesivamente.

    …pero eliminar NULL es indefinido. Por ejemplo, usted no puede probar si una referencia es NULA (por ejemplo, &ref == NULL).
    El número 2 es no verdad. Una de las referencias no es simplemente «otro nombre para la misma variable.» Las referencias pueden ser pasados a las funciones, almacenados en las clases, etc. de una manera muy similar a los punteros. Existen independientemente de las variables que elija.
    Brian, la pila no es relevante. Las referencias y los punteros no tener espacio en la pila. Ambos pueden ser asignados en el montón.
    Brian, el hecho de que una variable (en este caso de un puntero o referencia) requiere espacio no no significa que se requiere un espacio en la pila. Punteros y referencias, no solo se puede punto para el montón, en realidad pueden ser asignados en el montón.
    otro importante diff: las referencias no pueden ser embutidos en una matriz

    OriginalEl autor

  2. 317

    ¿Qué es una referencia de C++ (para los programadores de C)

    Un referencia puede ser pensado como un puntero constante (que no debe confundirse con un puntero a un valor constante!) con cambio automático de direccionamiento indirecto, es decir, el compilador se aplicará el * operador para usted.

    Todas las referencias deben ser inicializadas con un valor no nulo o compilación fallará. No es ni posible obtener la dirección de una referencia, la dirección de operador devolverá la dirección de la referencia de valor en su lugar – ni es posible hacer aritmética de las referencias.

    Los programadores de C podría aversión C++ referencias como no será más evidente cuando direccionamiento indirecto ocurre o si un argumento se pasa por valor o por el puntero, sin mirar función de firmas.

    Los programadores de C++ puede rechazar el uso de punteros, ya que se consideran inseguros – aunque las referencias no son realmente más seguro que la constante de punteros, excepto en la mayoría de los casos triviales – falta la conveniencia de direccionamiento automático y llevar una diferente connotación semántica.

    Considere la siguiente declaración de la C++ preguntas frecuentes:

    Aunque la referencia es a menudo implementado utilizando una dirección en la
    subyacente del lenguaje ensamblador, por favor no pensar en una referencia como un
    gracioso puntero a un objeto. Una referencia es el objeto. Es
    no es un puntero al objeto, ni una copia del objeto. Es es la
    objeto.

    Pero si una referencia realmente fueron el objeto, ¿cómo podría haber referencias pendiente? En lenguajes no administrados, es imposible que las referencias a cualquier «más seguros» que los punteros – no, en general no es una forma confiable de alias de valores a través de los límites de ámbito!

    Por qué considero que C++ referencias útiles

    Viniendo de una C de fondo, C++ referencias puede parecer un poco tonto concepto, sino que debe utilizar en lugar de punteros donde sea posible: Automático de direccionamiento indirecto es conveniente, y las referencias que se hacen especialmente útil cuando se trata de RAII – pero no porque la percepción de seguridad ventaja, sino más bien porque hace que la escritura idiomática código menos torpe.

    RAII es uno de los conceptos centrales de C++, sino que interactúa no trivial con la copia de la semántica. Pasar objetos por referencia evita estos problemas no copiar está involucrado. Si las referencias no estaban presentes en el lenguaje, usted tendría que usar punteros, que son más engorroso, violando de esta manera el diseño del lenguaje principio de que las mejores prácticas de la solución debería ser más fácil que las alternativas.

    No, también se puede obtener una referencia colgante por la devolución automática de la variable por referencia.
    Es prácticamente imposible para un compilador para detectar, en el caso general. Considere una función miembro que devuelve una referencia a una variable de miembro de clase: que es seguro y no debe ser prohibido por el compilador. A continuación, una llamada que tiene un sistema automático de instancia de esa clase, que las llamadas de función miembro, y devuelve la referencia. Presto: colgando de referencia. Y sí, va a causar problemas, @kriss: ese es mi punto. Muchas personas afirman que una de las ventajas de las referencias más punteros es que las referencias siempre son válidos, pero no es así.
    No, una referencia a un objeto de almacenamiento automático duración es muy diferente de un objeto temporal. De todos modos, se me acaba de proporcionar un contra-ejemplo a su declaración de que sólo se puede obtener una referencia no válida por desreferenciar un puntero no válido. Christoph es correcto, las referencias no son más seguros que los punteros, un programa que utiliza referencias exclusivamente todavía puede romper la seguridad de tipos.
    Las referencias no son un tipo de puntero. Se trata de un nuevo nombre para un objeto existente.
    verdadero si vas por el lenguaje, la semántica, no es cierto, si realmente nos fijamos en la implementación; C++ es mucho más «mágico» lenguaje C, y si se quita la magia a partir de las referencias, al final con un puntero

    OriginalEl autor Christoph

  3. 162

    Si quieres ser realmente pedante, hay una cosa que se puede hacer con una referencia que no se puede hacer con un puntero: extender el tiempo de vida de un objeto temporal. En C++ si se unen a una constante referencia a un objeto temporal, el tiempo de vida del objeto se convierte en la vida de la referencia.

    std::string s1 = "123";
    std::string s2 = "456";
    
    std::string s3_copy = s1 + s2;
    const std::string& s3_reference = s1 + s2;

    En este ejemplo s3_copy copias el objeto temporal que es un resultado de la concatenación. Mientras que s3_reference en esencia se convierte en el objeto temporal. Es realmente una referencia a un objeto temporal que ahora tiene la misma duración que la de referencia.

    Si usted intenta esto sin la const se producirá un error de compilación. Usted no puede obligar a un no-const referencia a un objeto temporal, ni puede tomar su dirección para que la materia.

    pero ¿cuál es el caso de uso para esto ?
    Bueno, s3_copy creará un temporal y, a continuación, copie construir en s3_copy mientras que s3_reference utiliza directamente el temporal. A continuación, para ser realmente pedante que usted necesita para mirar el Valor de Retorno de la Optimización de la cual se permite el compilador para eludir la copia de la construcción en el primer caso.
    La magia es muy poderosa. El objeto de toda la vida se extiende por el hecho de la const & vinculante, y sólo cuando la referencia queda fuera del ámbito al destructor de la real hace referencia tipo (como en comparación con el tipo de referencia, que podría ser una base). Ya que es una referencia, no rebanar tendrá lugar en el medio.
    Actualización para C++11: último debe leer la frase «no se puede obligar a un no-const lvalue referencia a un temporal» porque tú enlazar un no-const r-value referencia a un temporal, y tiene el mismo toda la vida-se extiende el comportamiento.
    El uso de clave de esto es derivadas de clases. Si no hay herencia de por medio, y podría así el valor de uso de la semántica, que será barato o gratis debido a RVO/mover construcción. Pero si usted tiene Animal x = fast ? getHare() : getTortoise() luego x se enfrentará el clásico rebanar problema, mientras que Animal& x = ... funcionará correctamente.

    OriginalEl autor Matt Price

  4. 114

    Contrario a la opinión popular, es posible tener una referencia de que es NULO.

    int * p = NULL;
    int & r = *p;
    r = 1;  //crash! (if you're lucky)

    Es cierto, es mucho más difícil de hacer con una referencia, pero si lo consigues, te voy a arrancar los pelos tratando de encontrarlo. Las referencias son no intrínsecamente seguros en C++!

    Técnicamente, este es un referencia no válida, no una referencia nula. C++ no soporta referencias nulas como un concepto, como se puede encontrar en otros idiomas. Hay otros tipos de referencias inválidas así. Cualquier referencia no válida plantea el espectro de un comportamiento indefinido, así como el uso de un puntero no válido haría.

    El error real es en el de eliminar el puntero NULL, antes de la asignación a una referencia. Pero yo no soy consciente de que cualquier compiladores que generan errores en esa condición – el error se propaga en un punto más adelante en el código. Eso es lo que hace que este problema sea tan insidiosa. La mayoría de las veces, si usted desreferenciar un puntero NULL, sufre un accidente justo en ese lugar y que no toma mucho de depuración de averiguar.

    Mi ejemplo anterior es corto y artificial. He aquí una más en el mundo real ejemplo.

    class MyClass
    {
        ...
        virtual void DoSomething(int,int,int,int,int);
    };
    
    void Foo(const MyClass & bar)
    {
        ...
        bar.DoSomething(i1,i2,i3,i4,i5);  //crash occurs here due to memory access violation - obvious why?
    }
    
    MyClass * GetInstance()
    {
        if (somecondition)
            return NULL;
        ...
    }
    
    MyClass * p = GetInstance();
    Foo(*p);

    Quiero reiterar que la única manera de obtener una referencia nula es a través de la malformación de código, y una vez que usted está consiguiendo un comportamiento indefinido. Es nunca tiene sentido buscar una referencia nula; por ejemplo, usted puede tratar de if(&bar==NULL)..., pero el compilador podría optimizar la declaración de la existencia! Una referencia válida que nunca puede ser NULA por lo que desde el compilador de vista de la comparación es siempre falso, y es libre de eliminar la if cláusula del código muerto – esta es la esencia de un comportamiento indefinido.

    La forma correcta para mantenerse fuera de problemas es evitar desreferenciar un puntero NULO para crear una referencia. He aquí una forma automatizada para lograr esto.

    template<typename T>
    T& deref(T* p)
    {
        if (p == NULL)
            throw std::invalid_argument(std::string("NULL reference"));
        return *p;
    }
    
    MyClass * p = GetInstance();
    Foo(deref(p));

    Para una más vieja mirada a este problema de alguien con mejores habilidades de escritura, consulte Referencias Nulas de Jim Hyslop y Herb Sutter.

    Para otro ejemplo de los peligros de desreferenciar un puntero nulo ver Exponer un comportamiento indefinido cuando tratando de puerto código para otra plataforma por Raymond Chen.

    El código en cuestión contiene un comportamiento indefinido. Técnicamente no se puede hacer nada con un puntero nulo excepto establecer y comparar. Una vez que el programa llama a un comportamiento indefinido, se puede hacer cualquier cosa, incluyendo aparecen a funcionar correctamente hasta que usted está dando una demostración de que el gran jefe.
    mark tiene un argumento válido. el argumento de que un puntero puede ser NULL y no por ello tiene que comprobar no es real: si usted dice que requiere una función que no es NULO, entonces la persona que llama tiene que hacer eso. así que si la persona que llama no es la invocación de un comportamiento indefinido. al igual que marcos hizo con la mala referencia
    La descripción es errónea. Este código puede o no puede crear una referencia de que es NULO. Su comportamiento es indefinido. Podría crear un perfectamente válido de referencia. Podría no crear ninguna referencia en absoluto.
    Schwartz, si yo estábamos hablando de la forma en que las cosas tenían que trabajar de acuerdo a la norma, tendría que ser la correcta. Pero que no lo que estoy hablando, estoy hablando sobre la realidad de la conducta observada con un muy popular compilador, y la extrapolación basada en mi conocimiento de la típica compiladores y arquitecturas de CPU a lo que probablemente a suceder. Si usted cree que las referencias a ser superior a los punteros porque son más seguros y no consideran que las referencias puede ser malo, usted va a ser sorprendido por un simple problema algún día como yo era.
    Desreferenciar un puntero nulo es malo. Cualquier programa que hace que, incluso para inicializar una referencia que está mal. Si usted está inicializando una referencia de un puntero debe comprobar siempre que el puntero es válido. Incluso si se realiza correctamente el objeto subyacente puede ser eliminado en cualquier momento de salir de la referencia para referirse a los no-objeto existente, a la derecha? Lo que están diciendo es buen material. Creo que el verdadero problema aquí es que la referencia NO deben ser verificados para «nullness» cuando ves uno, y el puntero debe ser, como mínimo, afirmó.

    OriginalEl autor Mark Ransom

  5. 107

    Aparte de azúcar sintáctico, una referencia es un const puntero (no puntero a una const). Se debe establecer lo que se refiere a cuando se declara la variable de referencia, y usted puede cambiar más adelante.

    Actualización: ahora que me pongo a pensar un poco más, hay una diferencia importante.

    Un puntero const del destino puede ser sustituido por tomar su dirección y el uso de una constante de reparto.

    Una referencia del destino no puede ser reemplazado en cualquier forma corta de la UB.

    Esto debería permitir que el compilador para hacer más de optimización en una referencia.

    Creo que esta es la mejor respuesta por el momento. Otros hablan de referencias y punteros como son animales diferentes y, a continuación, exponer cómo se diferencian en su comportamiento. No hacer las cosas más fáciles, en mi humilde opinión. Siempre he entendido referencias como un T* const con diferentes azúcar sintáctico (que ocurre para eliminar un montón de * y & a partir de su código).
    imagínese tratando de hacer cout << 42 << "hello" << endl sin referencias
    Corto y mejor respuesta
    «Un puntero const del destino puede ser sustituido por tomar su dirección y el uso de una constante de reparto.» Hacerlo es un comportamiento indefinido. Consulte stackoverflow.com/questions/25209838/… para obtener más detalles.
    Tratando de cambiar el referente de una referencia o el valor de un puntero const (o cualquier const escalar) es la igualdad ilegal. Lo que usted puede hacer: quitar una constante de calificación, que fue agregado por la conversión implícita: int i; int const *pci = &i; /* implicit conv to const int* */ int *pi = const_cast<int*>(pci); está bien.

    OriginalEl autor Arkadiy

  6. 104

    Ha olvidado la parte más importante:

    miembro-acceso con punteros utiliza ->

    miembro-acceso con referencias usos .

    foo.bar es claramente superior a foo->bar de la misma manera que vi es claramente superior a Emacs 🙂

    Edwards >miembro-acceso con punteros utiliza -> >miembro-acceso con referencias de usos . Esto no es 100% cierto. Usted puede tener una referencia a un puntero. En este caso, usted tendría acceso a los miembros de de referencia de puntero usando -> struct Nodo { Nodo *siguiente; }; Nodo *primero; // p es una referencia a un puntero void foo(Nodo*&p) { p->siguiente = primero; } Nodo *bar = new Nodo; foo(bar); — OP: ¿Está usted familiarizado con los conceptos de rvalues y lvalues?
    Punteros inteligentes tienen ambos . (métodos de puntero inteligente de la clase) y -> (métodos de tipo subyacente).
    Orion Edwards instrucción en realidad es 100% cierto. «acceso a los miembros de [la] de referencia de puntero» Un puntero no tiene ninguno de sus miembros. El objeto, el puntero se refiere a los miembros, y el acceso a ellas es exactamente lo que -> proporciona referencias a los punteros, así como con el propio puntero.
    ¿por qué es que . y -> tiene algo que ver con vi y emacs 🙂
    se trataba de una broma, y probablemente no tiene sentido para hablantes no nativos de inglés. Mis disculpas. Para explicar, si vi es mejor que emacs es totalmente subjetiva. Algunas personas piensan que la vi es muy superior, y otros piensan exactamente lo contrario. Del mismo modo, creo que el uso de . es mejor que el uso de ->, pero como vi vs emacs, es totalmente subjetivo y no se puede probar nada

    OriginalEl autor Orion Edwards

  7. 62

    En realidad, una referencia no es realmente como un puntero.

    Un compilador que mantiene «referencias» a las variables, la asociación de un nombre con una dirección de memoria; eso es su trabajo para traducir cualquier nombre de variable a una dirección de memoria cuando se compila.

    Al crear una referencia, sólo decirle al compilador que asignar otro nombre a la variable de puntero; es por eso que las referencias no pueden «apuntar a null», debido a que una variable no puede ser y no ser.

    Punteros son variables; contiene la dirección de otra variable, o puede ser null. Lo importante es que un puntero tiene un valor, mientras que una referencia sólo tiene una variable que hace referencia.

    Ahora algunos explicación del código real:

    int a = 0;
    int& b = a;

    Aquí no se está creando otra variable que apunta a a; son sólo añadir otro nombre a la memoria el contenido de la celebración el valor de a. Esta memoria tiene ahora dos nombres, a y b, y se puede abordar utilizando cualquiera de los dos nombres.

    void increment(int& n)
    {
        n = n + 1;
    }
    
    int a;
    increment(a);

    Cuando se llama a una función, el compilador genera por lo general los espacios de memoria para los argumentos para ser copiadas. La función de la firma define los espacios que deberían ser creados y le da el nombre que se debe utilizar para estos espacios. Declarar un parámetro como referencia le dice al compilador que utilice la variable de entrada al espacio de memoria en lugar de asignar un nuevo espacio de memoria durante la llamada al método. Puede parecer extraño decir que su función será directamente la manipulación de una variable declarada en el ámbito de la llamada, pero recuerda que cuando la ejecución de código compilado, no hay más alcance; no es simplemente el plano de la memoria, y su código de la función de poder manipular las variables.

    Ahora puede haber algunos casos en los que el compilador no puede ser capaz de saber la referencia a la hora de compilar, como cuando se utiliza un externo variable. Para una referencia puede o no puede ser implementado como un puntero en el código subyacente. Pero en los ejemplos que te di, lo más probable es que no se puede implementar con un puntero.

    Una referencia es una referencia a la l-valor, no necesariamente a una variable. Debido a eso, es mucho más cerca de un puntero de un alias real (en tiempo de compilación de constructo). Ejemplos de expresiones que pueden ser referenciados son *p o, incluso, *p++
    A la derecha, estaba recordando el hecho de que una referencia no siempre puede insertar una nueva variable en la pila con la forma de puntero.
    Se actuará de la misma como un puntero… si la función está alineada, tanto de referencia, y el puntero será optimizado de distancia. Si hay una llamada a una función, la dirección del objeto deberá ser pasados a la función.
    int *p = NULL; int &r=*p; referencia que apunta a NULL; if(r){} -> boOm 😉
    Este énfasis en la fase de compilación, parece agradable, hasta que recuerda que las referencias pueden ser pasados en tiempo de ejecución, momento en el cual estática aliasing sale de la ventana. (Y luego, las referencias son implementado como punteros, pero la norma no requiere de este método).

    OriginalEl autor Vincent Robert

  8. 58

    Referencias son muy similares a los punteros, pero están diseñados específicamente para ser útil para la optimización de compiladores.

    • Referencias son diseñados de tal forma que es considerablemente más fácil para el compilador para rastrear la referencia alias que las variables. Dos de las principales características son muy importantes: no «de referencia de la aritmética» y no de la reasignación de referencias. Estos permiten al compilador para averiguar cuál de las referencias alias que las variables en tiempo de compilación.
    • Referencias se permite hacer referencia a variables que no tienen direcciones de memoria, tales como aquellos que el compilador elige poner en registros. Si usted toma la dirección de una variable local, es muy difícil para el compilador para ponerlo en un registro.

    Como un ejemplo:

    void maybeModify(int& x); //may modify x in some way
    
    void hurtTheCompilersOptimizer(short size, int array[])
    {
        //This function is designed to do something particularly troublesome
        //for optimizers. It will constantly call maybeModify on array[0] while
        //adding array[1] to array[2]..array[size-1]. There's no real reason to
        //do this, other than to demonstrate the power of references.
        for (int i = 2; i < (int)size; i++) {
            maybeModify(array[0]);
            array[i] += array[1];
        }
    }

    Un compilador de optimización puede darse cuenta de que estamos accediendo a un[0] y a[1] un buen montón. Sería el amor a optimizar el algoritmo para:

    void hurtTheCompilersOptimizer(short size, int array[])
    {
        //Do the same thing as above, but instead of accessing array[1]
        //all the time, access it once and store the result in a register,
        //which is much faster to do arithmetic with.
        register int a0 = a[0];
        register int a1 = a[1]; //access a[1] once
        for (int i = 2; i < (int)size; i++) {
            maybeModify(a0); //Give maybeModify a reference to a register
            array[i] += a1;  //Use the saved register value over and over
        }
        a[0] = a0; //Store the modified a[0] back into the array
    }

    Hacer una optimización, es necesario demostrar que nada puede cambiar la matriz[1] durante la llamada. Esto es bastante fácil de hacer. yo no es nunca inferior a 2, por lo que la matriz[i] nunca puede referirse a la matriz[1]. maybeModify() está dada a0 como referencia (aliasing matriz[0]). Porque no hay ninguna «referencia» de la aritmética, el compilador sólo tiene que demostrar que maybeModify nunca se obtiene la dirección de x, y se ha demostrado que no cambia nada de la matriz[1].

    También tiene que probar que no hay formas de que una llamada futura podría leer/escribir a[0], mientras que tenemos un registro temporal copia de la misma en a0. Esto es a menudo trivial demostrar, porque en muchos casos es obvio que la referencia nunca se almacenan en una estructura permanente, como una instancia de la clase.

    Ahora hacer lo mismo con los punteros

    void maybeModify(int* x); //May modify x in some way
    
    void hurtTheCompilersOptimizer(short size, int array[])
    {
        //Same operation, only now with pointers, making the
        //optimization trickier.
        for (int i = 2; i < (int)size; i++) {
            maybeModify(&(array[0]));
            array[i] += array[1];
        }
    }

    El comportamiento es el mismo; sólo que ahora es mucho más difícil de probar que maybeModify no modificar la matriz[1], porque ya se dio un puntero; el gato está fuera de la bolsa. Ahora tiene que hacer mucho más difícil la prueba: un análisis estático de maybeModify para demostrar que nunca escribe &x + 1. También tiene que demostrar que nunca guarda fuera un puntero que puede referirse a la matriz[0], que es igual de complicado.

    Los compiladores modernos son cada vez mejor y mejor en el análisis estático, pero siempre es agradable para ayudarles a salir y el uso de referencias.

    De curso, salvo que tales inteligente optimizaciones, los compiladores de hecho su vez referencias a los punteros cuando sea necesario.

    EDICIÓN: Cinco años después de la publicación de esta respuesta, me encontré con una técnica real de la diferencia, donde las referencias son más que simplemente una manera diferente de mirar la misma abordar el concepto. Las referencias pueden modificar la vida útil de los objetos temporales en una forma en que los punteros no.

    F createF(int argument);
    
    void extending()
    {
        const F& ref = createF(5);
        std::cout << ref.getArgument() << std::endl;
    };

    Normalmente temporal de los objetos, tales como el creado por la llamada a createF(5) son destruidos al final de la expresión. Sin embargo, por la unión que es el objeto de una referencia, ref, C++, se extenderá la vida útil de ese objeto temporal hasta ref sale del ámbito.

    Cierto, el cuerpo tiene que ser visible. Sin embargo, la determinación de que maybeModify no toma la dirección de cualquier cosa relacionada con x es mucho más fácil de demostrar que un montón de aritmética de punteros no se produce.
    Creo que el optimizador de que ya hace «un montón de puntero arithemetic no se produce» de verificación para un montón de otras razones.
    «Las referencias son muy similares a los punteros» – semántico, en los contextos apropiados – pero en términos de código generado, sólo en algunas implementaciones y no a través de cualquier definición/requisito. Yo sé que usted ha señalado, y no estoy en desacuerdo con alguno de tus post, en términos prácticos, pero tenemos demasiados problemas ya con la gente que lee mucho, la taquigrafía descripciones como «las referencias son como/se implementan generalmente como punteros’.
    Tengo la sensación de que alguien erróneamente marcado como obsoleto un comentario a lo largo de las líneas de void maybeModify(int& x) { 1[&x]++; }, lo que los otros comentarios de arriba están discutiendo

    OriginalEl autor Cort Ammon

  9. 37

    Una referencia no puede ser nunca NULL.

    Vea la Marca de Rescate de la respuesta para un contra-ejemplo. Esto es lo más a menudo afirmó mito acerca de las referencias, pero es un mito. La única garantía de que usted tiene por la norma, que de inmediato han UB cuando usted tiene una referencia NULA. Pero eso equivale a decir «Este coche es seguro, nunca puede salir de la carretera. (No tomamos ninguna responsabilidad por lo que puede suceder si usted conducirla fuera de la carretera, de todos modos. Es posible que acaba de explotar.)»
    En un programa válido, una referencia no puede ser null. Pero un puntero se puede. Esto no es un mito, es un hecho.
    Sí, válido programas de permanecer en el camino. Pero no hay ninguna barrera de tráfico para exigir que el programa realmente hace. Grandes partes de la carretera son en realidad faltan marcas. Así que es muy fácil salirse de la carretera en la noche. Y es crucial para la depuración de errores tales que saber esto puede suceder: la referencia nula puede propagar antes de que se bloquea el programa, al igual que un puntero nulo puede. Y cuando lo hace tiene un código como void Foo::bar() { virtual_baz(); } que segfaults. Si no son conscientes de que las referencias pueden ser nulos, no se puede rastrear el null de vuelta a su origen.
    int *p = NULL; int &r=*p; referencia que apunta a NULL; if(r){} -> boOm 😉 –
    int &r=*p; es un comportamiento indefinido. En ese punto, usted no tiene una referencia que apunta a NULL,» usted tiene un programa que no puede ser razonada sobre todo.

    OriginalEl autor

  10. 33

    Mientras tanto las referencias y los punteros se utilizan indirectamente el acceso a otro valor, hay dos diferencias importantes entre las referencias y los punteros. La primera es que una referencia se refiere siempre a un objeto: es un error definir una referencia sin inicializarla. El comportamiento de la asignación es la segunda diferencia importante: la Asignación de una referencia cambia el objeto de la cual la referencia es obligada; no volver a enlazar la referencia a otro objeto. Una vez inicializado, una referencia siempre se refiere al mismo objeto subyacente.

    Considerar estos dos fragmentos de programa. En la primera, se le asigna un puntero a otro:

    int ival = 1024, ival2 = 2048;
    int *pi = &ival, *pi2 = &ival2;
    pi = pi2;    //pi now points to ival2

    Después de la asignación, ival, el objeto abordado por pi permanece sin cambios. Los cambios en la asignación del valor de pi, haciendo que apunte a un objeto diferente. Ahora considere un programa similar que asigna dos referencias:

    int &ri = ival, &ri2 = ival2;
    ri = ri2;    //assigns ival2 to ival

    Este cambios en la asignación de ival, el valor de referencia por parte de ri, y no la referencia a sí mismo. Después de la asignación, las dos referencias todavía se refieren a sus objetos originales, y el valor de esos objetos es ahora igual de bien.

    «una referencia siempre se refiere a un objeto» es completamente falso

    OriginalEl autor Kunal Vyas

  11. 27

    Hay una diferencia semántica que puede parecer esotérico si usted no está familiarizado con el estudio de los lenguajes de computador en abstracto, o incluso académico de la moda.

    Al más alto nivel, la idea de las referencias es que son transparentes «alias». El equipo puede utilizar una dirección para hacerles el trabajo, pero usted no debe preocuparse de que: se supone que se debe pensar en ellos como «otro nombre» de un objeto existente y la sintaxis refleja. Ellos son más estrictos que los punteros para que su compilador puede de forma más fiable que avise cuando se acerca para crear una referencia colgante, que cuando estás a punto de crear un colgando puntero.

    Más allá de eso, por supuesto, hay algunas diferencias prácticas entre los punteros y referencias. La sintaxis para el uso de ellos es, obviamente, diferente, y usted no puede «re-asiento» referencias, tienen referencias a la nada, o los punteros a las referencias.

    OriginalEl autor Lightness Races in Orbit

  12. 22

    Una referencia es un alias para la otra variable, mientras que un puntero contiene la dirección de memoria de una variable. Las referencias son generalmente utilizados como parámetros de la función, de modo que el objeto pasado no es la copia, pero el objeto en sí.

        void fun(int &a, int &b); //A common usage of references.
        int a = 0;
        int &b = a; //b is an alias for a. Not so common to use. 

    OriginalEl autor fatma.ekici

  13. 18

    No importa la cantidad de espacio que ocupa, ya que en realidad no puede ver ningún efecto secundario (sin ejecutar código) de todo el espacio que ocuparía.

    Por otro lado, una diferencia importante entre las referencias y los punteros es que los empleos temporales asignados a const referencias vivir hasta que la constante de referencia sale del ámbito.

    Por ejemplo:

    class scope_test
    {
    public:
        ~scope_test() { printf("scope_test done!\n"); }
    };
    
    ...
    
    {
        const scope_test &test= scope_test();
        printf("in scope\n");
    }

    va a imprimir:

    in scope
    scope_test done!

    Este es el lenguaje mecanismo que permite ScopeGuard a trabajar.

    Usted no puede tomar la dirección de una referencia, pero eso no significa que no físicamente ocupan espacio. Restricción de optimizaciones, a la que más, sin duda alguna.
    El impacto no obstante, «Una referencia en la pila no ocupa espacio en absoluto» es totalmente falso.
    bueno, eso también depende del compilador. Pero sí, dicen que es un poco confuso. Supongo que sería menos confuso para eliminar sólo eso.
    En cualquier caso concreto puede o puede que no. Por lo que «no» como una categórica afirmación es incorrecta. Que es lo que estoy diciendo. 🙂 [No puedo recordar lo que la norma dice sobre el tema; que las normas de referencia de los miembros puede dar una regla general de «referencias pueden tomar hasta el espacio», pero no tengo mi copia de la norma conmigo aquí en la playa :D]

    OriginalEl autor MSN

  14. 18

    Esto se basa en la tutorial. Lo que está escrito hace que sea más claro:

    >>> The address that locates a variable within memory is
        what we call a reference to that variable. (5th paragraph at page 63)
    
    >>> The variable that stores the reference to another
        variable is what we call a pointer. (3rd paragraph at page 64)

    Simplemente para recordar que,

    >>> reference stands for memory location
    >>> pointer is a reference container (Maybe because we will use it for
    several times, it is better to remember that reference.)

    Lo que es más, como nos puede referirse a casi cualquier puntero tutorial, que es un puntero a un objeto que es apoyado por la aritmética de punteros que hace de puntero similar a una matriz.

    Vistazo a la siguiente instrucción,

    int Tom(0);
    int & alias_Tom = Tom;

    alias_Tom puede ser entendida como una alias of a variable (diferentes con typedef, que es alias of a type) Tom. Es también ACEPTAR para olvidar la terminología de dicha declaración es crear una referencia de Tom.

    Y si una clase tiene una variable de referencia, debe ser inicializado con un nullptr o un objeto válido de la lista de inicialización.
    La redacción de esta respuesta es demasiado confuso para ser de mucho uso real. También, @Misgevolution, están en serio recomendar a los lectores establecer una referencia con un nullptr? Has leído alguna otra parte de este hilo, o…?
    Mi mal, lo siento por esa estúpida cosa que me dijo. Debo de haber sido privados de sueño en ese momento. ‘inicializar con nullptr» es totalmente equivocado.

    OriginalEl autor Life

  15. 18

    Una referencia no es otro nombre dado a algunos de memoria. Es una inmutable puntero que es automáticamente de referencia en el uso. Básicamente se reduce a:

    int& j = i;

    Internamente se convierte en

    int* const j = &i;
    Esto no es lo que el Estándar de C++, dice, y no es necesario para el compilador para implementar las referencias en la forma descrita por tu respuesta.
    De cualquier manera que sea válido para un compilador de C++ para implementar una referencia es también una forma válida para implementar un const puntero. Que la flexibilidad no es prueba de que hay una diferencia entre una referencia y un puntero.
    Puede ser cierto que cualquier válida la aplicación de uno también es válida la aplicación de la otra, pero que no sigue de forma evidente a partir de las definiciones de estos dos conceptos. Una buena respuesta podría haber comenzado a partir de las definiciones, y demostraron por qué la afirmación acerca de los dos, siendo en última instancia la misma es verdadera. Esta respuesta parece ser algún tipo de comentario sobre algunas de las otras respuestas.
    Una referencia de la se otro nombre dado a un objeto. El compilador se le permite tener ningún tipo de aplicación, siempre y cuando usted no puede decir la diferencia, esto es conocido como el «como si» de la regla. La parte importante aquí es que usted no puede decir la diferencia. Si usted puede descubrir que un puntero no tiene almacenamiento, el compilador es un error. Si usted puede descubrir que una referencia no tiene almacenamiento, el compilador es todavía válidas.

    OriginalEl autor tanweer alam

  16. 15

    Una referencia a un puntero es posible en C++, pero la inversa no es posible significa un puntero a una referencia no es posible. Una referencia a un puntero proporciona un limpiador de sintaxis para modificar el puntero.
    Mira este ejemplo:

    #include<iostream>
    using namespace std;
    
    void swap(char * &str1, char * &str2)
    {
      char *temp = str1;
      str1 = str2;
      str2 = temp;
    }
    
    int main()
    {
      char *str1 = "Hi";
      char *str2 = "Hello";
      swap(str1, str2);
      cout<<"str1 is "<<str1<<endl;
      cout<<"str2 is "<<str2<<endl;
      return 0;
    }

    Y considerar la C versión del programa anterior. En C se tiene que utilizar el puntero a puntero múltiples (direccionamiento indirecto), y se lleva a la confusión y el programa puede parecer complicado.

    #include<stdio.h>
    /* Swaps strings by swapping pointers */
    void swap1(char **str1_ptr, char **str2_ptr)
    {
      char *temp = *str1_ptr;
      *str1_ptr = *str2_ptr;
      *str2_ptr = temp;
    }
    
    int main()
    {
      char *str1 = "Hi";
      char *str2 = "Hello";
      swap1(&str1, &str2);
      printf("str1 is %s, str2 is %s", str1, str2);
      return 0;
    }

    Visite el siguiente para obtener más información acerca de referencia a puntero:

    Como he dicho, un puntero a una referencia no es posible. Pruebe el siguiente programa:

    #include <iostream>
    using namespace std;
    
    int main()
    {
       int x = 10;
       int *ptr = &x;
       int &*ptr1 = ptr;
    }

    OriginalEl autor Destructor

  17. 14

    Hay una diferencia fundamental entre los punteros y referencias que no me vea nadie había mencionado: las referencias a habilitar el paso por referencia de la semántica en los argumentos de la función. Los punteros, aunque no es visible a primera no: sólo proporcionan pasar-por-valor de la semántica. Esto ha sido muy bien descrito en este artículo.

    Saludos,
    &rzej

    Referencias y enlaces son las dos asas. Ambos dan la semántica donde su objeto se pasa por referencia, pero el mango es copiado. Ninguna diferencia. (Hay otras maneras de tener manijas también, como una clave para la búsqueda en un diccionario)
    Yo también solía pensar de esta forma. Pero ver el artículo relacionado describiendo por qué no es así.
    Eso es sólo una muy larga versión de la frase en mi comentario: El mango es copiado.
    Necesito más explicación sobre este «El mango es copiado». Entiendo que algunos básicos idea, pero creo que físicamente la referencia y el puntero de señalar la ubicación de memoria de la variable. Es como alias almacena el valor de la variable y la actualiza como valor de la variable es el cambio o algo más? Soy novato, y por favor, no la bandera como una pregunta estúpida.
    Falso. En ambos casos, de paso por valor que está ocurriendo. La referencia se pasan por valor y el puntero se pasa por valor. Diciendo de otra manera, que confunde a los novatos.

    OriginalEl autor Andrzej

  18. 14

    Puedo usar referencias a menos que necesite cualquiera de estos:

    • Punteros Null puede ser utilizado como un
      valor de centinela, a menudo, una manera barata de
      evitar la sobrecarga de funciones o el uso de
      un bool.

    • Puede hacer operaciones aritméticas en un puntero.
      Por ejemplo, p += offset;

    Usted puede escribir &r + offset donde r fue declarado como referencia

    OriginalEl autor Aardvark

  19. 13

    En el riesgo de agregar a la confusión, quiero tirar en alguna entrada, estoy seguro de que en su mayoría depende de cómo el compilador implementa referencias, pero en el caso de gcc la idea de que una referencia sólo puede apuntar a una variable en la pila no es realmente correcto, tome esto por ejemplo:

    #include <iostream>
    int main(int argc, char** argv) {
        //Create a string on the heap
        std::string *str_ptr = new std::string("THIS IS A STRING");
        //Dereference the string on the heap, and assign it to the reference
        std::string &str_ref = *str_ptr;
        //Not even a compiler warning! At least with gcc
        //Now lets try to print it's value!
        std::cout << str_ref << std::endl;
        //It works! Now lets print and compare actual memory addresses
        std::cout << str_ptr << " : " << &str_ref << std::endl;
        //Exactly the same, now remember to free the memory on the heap
        delete str_ptr;
    }

    Que genera esta:

    THIS IS A STRING
    0xbb2070 : 0xbb2070

    Si usted nota incluso las direcciones de memoria son exactamente los mismos, es decir, la referencia es correctamente apuntando a una variable en el montón! Ahora bien, si usted realmente desea conseguir freaky, esto también funciona:

    int main(int argc, char** argv) {
        //In the actual new declaration let immediately de-reference and assign it to the reference
        std::string &str_ref = *(new std::string("THIS IS A STRING"));
        //Once again, it works! (at least in gcc)
        std::cout << str_ref;
        //Once again it prints fine, however we have no pointer to the heap allocation, right? So how do we free the space we just ignorantly created?
        delete &str_ref;
        /*And, it works, because we are taking the memory address that the reference is
        storing, and deleting it, which is all a pointer is doing, just we have to specify
        the address with '&' whereas a pointer does that implicitly, this is sort of like
        calling delete &(*str_ptr); (which also compiles and runs fine).*/
    }

    Que genera esta:

    THIS IS A STRING

    Por tanto, una referencia ES un puntero bajo el capó, ambos son sólo almacenar una dirección de memoria, donde la dirección está señalando es irrelevante, ¿qué crees que pasaría si me llama std::cout << str_ref; DESPUÉS de llamar a eliminar &str_ref? Bueno, es obvio que compila bien, pero a causa de un fallo de segmentación en tiempo de ejecución porque ya no apunta a una variable válido, que esencialmente tiene rota la referencia que todavía existe (hasta que cae fuera del ámbito), pero es inútil.

    En otras palabras, una referencia no es sino un puntero que tiene el puntero de la mecánica extraída de distancia, lo que es más seguro y más fácil de usar (no accidental puntero de matemáticas, no mezclar ‘.’ y ‘->’, etc.), suponiendo que no se trate de cualquier tontería como mis ejemplos anteriores 😉

    Ahora independientemente de cómo un compilador maneja referencias, siempre tienen algún tipo de puntero bajo el capó, porque una referencia debe referirse a una variable específica a una determinada dirección de memoria para que funcione como se espera, no hay vuelta de este (de ahí el término «referencia»).

    La única regla que es importante recordar que con las referencias que deben ser definidos en el momento de la declaración (con la excepción de una referencia en un encabezado, en ese caso debe ser definido en el constructor, después de que el objeto es contenida en esta construido demasiado tarde para definir).

    Recordar, mis ejemplos anteriores son sólo eso, ejemplos de lo que una referencia es, que usted nunca desea utilizar una referencia en los caminos! Para el buen uso de una referencia hay un montón de respuestas por aquí ya que golpear el clavo en la cabeza

    OriginalEl autor Tory

  20. 12

    Otra diferencia es que usted puede tener punteros a un tipo void (y significa puntero a cualquier cosa) pero las referencias al vacío están prohibidos.

    int a;
    void * p = &a; //ok
    void & p = a;  // forbidden

    Yo no puedo decir que estoy muy contento con esta diferencia. Prefiero sería permitido con el significado de referencia a cualquier cosa con una dirección y, en caso contrario el mismo comportamiento para las referencias. Esto permitiría definir algunos equivalentes de funciones de la biblioteca C como memcpy el uso de referencias.

    OriginalEl autor kriss

  21. 12

    Ambas referencias y enlaces se pueden utilizar para cambiar las variables locales de una función dentro de otra función. Dos de ellos también puede ser usado para guardar la copia de los objetos más grandes cuando se pasan como argumentos a funciones o devolución de funciones, para conseguir el aumento de la eficiencia.
    A pesar de las similitudes, existen las siguientes diferencias entre las referencias y los punteros.

    Referencias son menos eficaces que los punteros

    1) una Vez que se crea una referencia, no puede ser más tarde hizo referencia a otro objeto; no puede estar sentados en una nueva mesa. Esto se hace a menudo con los punteros.

    2) Referencias no puede ser NULL. Los punteros son hechas a menudo NULL para indicar que no están apuntando a cualquier otra cosa.

    3) Una referencia debe ser inicializado cuando se declara. No existe tal restricción con punteros

    Debido a las limitaciones anteriores, las referencias en C++ no puede ser utilizado para la implementación de estructuras de datos como Lista Enlazada, un Árbol, etc. En Java, las referencias no tienen restricciones anteriores, y se puede utilizar para implementar todas las estructuras de datos. Referencias de ser más potentes en Java, es el principal motivo de Java no necesita punteros.

    Referencias son más seguros y fáciles de usar:

    1) Seguro: Desde las referencias deben ser inicializados, salvaje referencias como salvajes punteros son poco probable que exista. Todavía es posible tener referencias que no se refieren a una ubicación válida

    2) Fácil de usar: las Referencias no necesita eliminar la referencia del operador para acceder al valor. Pueden utilizarse como variables normales. ‘&’ operador sólo es necesaria en el momento de la declaración. Además, los miembros de un objeto de referencia se puede acceder con el operador de punto (‘.’), a diferencia de los punteros donde el operador flecha (->) es necesario para tener acceso a los miembros.

    Junto con las razones anteriores, hay pocos lugares como constructor de copia argumento donde el puntero no puede ser utilizado. La referencia debe ser utilizado pasar el argumento en el constructor de copia. Del mismo modo referencias debe ser utilizado para la sobrecarga de algunos operadores ++.

    OriginalEl autor Yogeesh H T

  22. 10

    También, una referencia que es un parámetro a una función que está alineada puede ser manejado de manera diferente que un puntero.

    void increment(int *ptrint) { (*ptrint)++; }
    void increment(int &refint) { refint++; }
    void incptrtest()
    {
        int testptr=0;
        increment(&testptr);
    }
    void increftest()
    {
        int testref=0;
        increment(testref);
    }

    Muchos compiladores cuando inline el puntero versión de una realidad de la fuerza de una escritura a la memoria (estamos tomando la dirección de forma explícita). Sin embargo, van a salir de la referencia en un registro que es más óptimo.

    De curso, para funciones que no están alineadas al puntero y de referencia generar el mismo código, y siempre es mejor pasar de las características intrínsecas por el valor que por la referencia, si no se modifican y devuelto por la función.

    OriginalEl autor Adisak

  23. 10

    Este programa podría ayudar en la comprensión de la respuesta de la pregunta. Este es un programa simple de una referencia de la «j» y un «puntero ptr apunta a la variable «x».

    #include<iostream>
    
    using namespace std;
    
    int main()
    {
    int *ptr=0, x=9; //pointer and variable declaration
    ptr=&x; //pointer to variable "x"
    int & j=x; //reference declaration; reference to variable "x"
    
    cout << "x=" << x << endl;
    
    cout << "&x=" << &x << endl;
    
    cout << "j=" << j << endl;
    
    cout << "&j=" << &j << endl;
    
    cout << "*ptr=" << *ptr << endl;
    
    cout << "ptr=" << ptr << endl;
    
    cout << "&ptr=" << &ptr << endl;
        getch();
    }

    Ejecutar el programa y ver la salida y vas a entender.

    También, repuesto de 10 minutos y ver este video: https://www.youtube.com/watch?v=rlJrrGV0iOg

    OriginalEl autor Arlene Batada

  24. 9

    Otro uso interesante de las referencias es la de proporcionar un argumento por defecto de un tipo definido por el usuario:

    class UDT
    {
    public:
       UDT() : val_d(33) {};
       UDT(int val) : val_d(val) {};
       virtual ~UDT() {};
    private:
       int val_d;
    };
    
    class UDT_Derived : public UDT
    {
    public:
       UDT_Derived() : UDT() {};
       virtual ~UDT_Derived() {};
    };
    
    class Behavior
    {
    public:
       Behavior(
          const UDT &udt = UDT()
       )  {};
    };
    
    int main()
    {
       Behavior b; //take default
    
       UDT u(88);
       Behavior c(u);
    
       UDT_Derived ud;
       Behavior d(ud);
    
       return 1;
    }

    El valor predeterminado sabor utiliza el ‘enlazar const referencia temporal de» aspecto de referencias.

    OriginalEl autor Don Wakefield

  25. 9

    Me siento como todavía hay otro punto que no ha sido cubierto.

    A diferencia de los punteros, referencias son sintácticamente equivalentes para el objeto al que se refieren, es decir, cualquier operación que puede ser aplicada a un objeto de obras de referencia, y con exactamente la misma sintaxis (la excepción es, por supuesto, la inicialización).

    Mientras que esto puede parecer superficial, creo que esta propiedad es crucial para un número de características de C++, por ejemplo:

    • Plantillas. Desde los parámetros de la plantilla son de pato escrito, sintáctico de las propiedades de un tipo que es todo lo que importa, por lo que a menudo la misma plantilla que puede utilizarse tanto con T y T&.

      (o std::reference_wrapper<T> que todavía se basa en una conversión implícita
      a T&)

      Las plantillas que cubren tanto T& y T&& son aún más comunes.

    • Lvalues. Considere la declaración str[0] = 'X'; Sin referencias sólo funcionan para c-strings (char* str). Volviendo al personaje por referencia permite que el usuario define las clases tienen la misma notación.

    • Copia de constructores. Sintácticamente tiene sentido pasar objetos a copiar los constructores, y no punteros a objetos. Pero simplemente no hay manera de que un constructor de copia para tomar un objeto de valor que resultaría en una llamada recursiva a la misma constructor de copia. Esto deja a referencias como la única opción aquí.

    • Sobrecargas de operador. Con referencias es posible introducir direccionamiento indirecto a un operador de call – decir, operator+(const T& a, const T& b) mientras que la retención de la misma notación de infijo. Esto también funciona para regular funciones sobrecargadas.

    Estos puntos de empoderar a una parte considerable de C++ y la librería estándar de modo que esta es una importante propiedad de las referencias.

    «conversión implícita» un cast es una sintaxis de la construcción, que existe en la gramática; un cast es siempre explícito

    OriginalEl autor Ap31

  26. 8

    Tal vez algunas metáforas ayudará;
    En el contexto de su escritorio screenspace –

    • Una referencia requiere especificar una ventana real.
    • Un puntero requiere la ubicación de una pieza de espacio en pantalla que le asegure que va a contener cero o más instancias de ese tipo de ventana.

    OriginalEl autor George R

  27. 7

    Hay una muy importante que no diferencia técnica entre los punteros y referencias: Un argumento que se pasa a una función de puntero es mucho más visible que un argumento se pasa a una función por referencia no const. Por ejemplo:

    void fn1(std::string s);
    void fn2(const std::string& s);
    void fn3(std::string& s);
    void fn4(std::string* s);
    
    void bar() {
        std::string x;
        fn1(x);  //Cannot modify x
        fn2(x);  //Cannot modify x (without const_cast)
        fn3(x);  //CAN modify x!
        fn4(&x); //Can modify x (but is obvious about it)
    }

    C, una llamada que parece fn(x) sólo pueden ser pasados por valor, por lo que definitivamente no puede modificar x; modificar un argumento que usted necesita para pasar un puntero fn(&x). Así que si un argumento no fue precedida por una & usted sabía que no sería modificado. (A la inversa, el & significa modificado, no era cierto, porque a veces tienen que pasar grandes de sólo-lectura de las estructuras de const puntero.)

    Algunos argumentan que esta es una característica útil cuando la lectura del código, que los parámetros de puntero siempre debe ser utilizado para los parámetros modificables en lugar de no-const referencias, incluso si la función nunca se espera un nullptr. Es decir, aquellas personas argumentan que la función de firmas como fn3() anterior no debe ser permitido. Google C++ guía de estilo son un ejemplo de esto.

    OriginalEl autor Arthur Tacca

  28. 6

    Diferencia entre el puntero y de referencia

    Un puntero puede ser inicializado a 0 y una referencia no. De hecho, una referencia también debe referirse a un objeto, sino un puntero puede ser el puntero null:

    int* p = 0;

    Pero no podemos int& p = 0; y también int& p=5 ;.

    De hecho, para hacerlo correctamente, debemos tener declara y define un objeto en el primero, luego podemos hacer una referencia a ese objeto, por lo que la correcta implementación del código anterior será:

    Int x = 0;
    Int y = 5;
    Int& p = x;
    Int& p1 = y;

    Otro punto importante es que se le puede hacer la declaración de un puntero sin inicializar sin embargo no hay tal cosa se puede hacer en el caso de referencia, que debe hacer referencia siempre a la variable u objeto. Sin embargo el uso de un puntero es arriesgado por lo general, se comprueba si el puntero está en realidad está apuntando a algo o no. En caso de no referencia de dicho cheque es necesario, porque ya sabemos que hace referencia a un objeto durante la declaración es obligatoria.

    Otra diferencia es que el puntero puede apuntar a otro objeto, sin embargo, la referencia es siempre hacer referencia al mismo objeto, tomemos este ejemplo:

    Int a = 6, b = 5;
    Int& rf = a;
    
    Cout << rf << endl; //The result we will get is 6, because rf is referencing to the value of a.
    
    rf = b;
    cout << a << endl; //The result will be 5 because the value of b now will be stored into the address of a so the former value of a will be erased

    Otro punto: Cuando tenemos una plantilla como un STL plantilla de este tipo de una plantilla de clase siempre devuelve una referencia a un puntero, para hacer fácil la lectura o la asignación de un nuevo valor utilizando el operador []:

    Std ::vector<int>v(10); //Initialize a vector with 10 elements
    V[5] = 5; //Writing the value 5 into the 6 element of our vector, so if the returned type of operator [] was a pointer and not a reference we should write this *v[5]=5, by making a reference we overwrite the element by using the assignment "="
    Aun podemos tener const int& i = 0.
    En este caso la referencia se utilizará sólo en leer que no se puede modificar esta referencia const, incluso mediante el uso de «const_cast» porque «const_cast» aceptar sólo puntero no de referencia.
    const_cast obras con referencias bastante bien: coliru.stacked-crooked.com/a/eebb454ab2cfd570
    usted está haciendo un modelo de referencia no echando una referencia probar esto; const int& i=; const_cast<int>(i); trato de tirar la constness de la referencia para hacer posible la escritura y la asignacion de un nuevo valor a la referencia, pero esto no es posible . por favor foco !!

    OriginalEl autor dhokar.w

  29. 5

    La diferencia es que no constante variable de puntero(que no debe confundirse con un puntero a constante) puede ser modificado en algún momento durante la ejecución del programa, se requiere el puntero de la semántica a ser utilizado(&,*) los operadores, mientras que las referencias se pueden establecer en la inicialización sólo(es por eso que se pueden configurar en la lista de inicializador de constructor sólo, pero de alguna manera no otra cosa) y el uso de valor normal de acceder a la semántica. Básicamente, las referencias se introdujo para permitir que el soporte para la sobrecarga de operadores como había leído en algunos muy viejo libro. Como alguien dijo en este hilo – puntero se puede establecer en 0 o cualquier valor que desee. 0(NULL, nullptr) significa que el puntero se inicializa con nada. Es un error eliminar la referencia a un puntero nulo. Pero en realidad, el puntero puede contener un valor que no apuntan a la correcta ubicación de la memoria. Las referencias a su vez, trate de no permitir a un usuario para inicializar una referencia a algo que no puede ser referenciada por el hecho de que siempre proporcione r-value de tipo correcto. Aunque hay un montón de maneras de hacer referencia variable se inicializa a una incorrecta ubicación de la memoria – es mejor para ti no para cavar hasta el fondo de los detalles. En el nivel de la máquina, tanto puntero y de referencia de trabajo de manera fluida a través de punteros. Digamos que en referencias esenciales son azúcar sintáctico. r-value referencias son diferentes, ellos son, naturalmente, de la pila o de montón de objetos.

    OriginalEl autor Zorgiev

  30. 2

    Siempre me decida por este regla de C++ Directrices básicas:

    Prefieren T* T sobre& cuando «no hay ningún argumento», es una opción válida

    El uso de funciones sobrecargadas que no tome punteros en lugar de permitir que nullptr, o el uso de la terminal de objetos, es discutible una solución mucho mejor, en lugar de permitir que nullptr como argumentos.
    Es probablemente la más limpia, pero a veces uno necesita para pasar rápidamente a los punteros de todo y puede haber casos en los que no te importa si el puntero es null o no.

    OriginalEl autor Hitokage

Dejar respuesta

Please enter your comment!
Please enter your name here