2009-03-20 15 views
10

Estaba leyendo C++ Faq Segunda edición, número de pregunta 32.08.Parámetro pasado por referencia const devuelto por const referencia

La pregunta frecuente dice que el parámetro pasado por la referencia const y devuelto por la referencia const puede causar referencia colgante.

Pero está bien si el parámetro se pasa por referencia y se devuelve por referencia.

Entendí que no es seguro en caso de referencia const, pero ¿cómo es seguro en caso de que el parámetro no sea referencia constante.

última línea de FAQ dice "Tenga en cuenta que si una función acepta un parámetro por referencia no constante (por ejemplo, f (cadena & s)), devolviendo una copia de este parámetro de referencia es segura debido a que un temporal no puede haber pasado por referencia no const ".

¡¡Necesito algo de información sobre esto !!

+0

No estoy seguro de lo que quieres decir con Faq Second edition. ¿Puedes publicar la URL a él? –

+0

http://www.amazon.com/FAQs-2nd-Marshall-P-Cline/dp/0201309831/ref=sr_1_1?ie=UTF8&s=books&qid=1237575374&sr=8-1 – anand

+0

bien, ya veo. muchas preguntas frecuentes por ahí y no estaba en la famosa faq C++ en línea y luego me pregunté qué era :) –

Respuesta

31

si tiene como

const Foo & bar(const Foo &f) { return f; } 

y lo llama como

const Foo &ret = bar(Foo()); 

Esto compila, pero el problema es que ahora 'RET' es una referencia colgante, porque el objeto temporal creado por la llamada a Foo() se libera después de que la barra retorna. La secuencia de ejecución detallado aquí es:

  1. Foo temporal se asigna
  2. bar se llama con una referencia al objeto temporal
  3. barra devuelve la referencia
  4. ahora que la barra ha devuelto el Foo temporal se libera
  5. la referencia está colgando como el objeto fue destruido

Sin embargo, si usted tenía Foo declarado como

Foo & bar(Foo &f) { return f; } 

entonces su prohibición de llamadas (Foo()) no sería aceptado por el compilador. Cuando pasa un objeto temporal a una función, solo puede tomarlo por referencia constante o como una copia; esto es parte de la definición del lenguaje.

+0

Edición: 'ref' debe ser 'ret' Lo que significa que const Foo & puede estar obligado a Foo() temporal pero Foo & no se puede vincular a Foo() temporal. ¿Alguna idea de por qué el compilador no permite esto? – anand

+2

antti, buena respuesta :) –

+0

no está permitido porque las referencias no confinadas tienen que referirse a objetos con nombre. eso es principalmente por seguridad, pero también tiene más razones teóricas. si un valor temporal no de clase, como int, pudiera vincularse a una referencia de noconst el int necesitaría una dirección (ser un objeto). pero no es un objeto, solo un valor –

3

Los temporales se pueden pasar por referencia constante: cuando la función retorna, los temporales se destruyen, por lo que el llamante queda con una referencia que cuelga.

Por ejemplo:

#include <iostream> 

using namespace std; 

int const& output(int const& x) 
{ 
    cout << x << endl; 

    return x; 
} 

int main() 
{ 
    int a = 1; 

    int const& ref1 = output(a); // OK 

    int const& ref2 = output(a+1); // bad 

    return 0; 
} 
1

creo que este ejemplo será útil:

const int& f(const int& n) 
{ 
    return n; 
} 

int f1(int& n) 
{ 
    return n; 
} 


int main(int argc, char **argv) 
{ 
    //Passing a reference to an anonymous object created by 
    //the compiler to function f() 
    const int& n = f(10); 

    //Undefined behavior here as the scope of the anonymous object 
    //was only till previous statement 
    int k = n + 10; 

    //Compiler error - Can not pass non-const reference to a anonymous object 
    int n = f1(10); 
} 
1

Here es una página sobre referencias C++ 0x rvalue que se inicia con un resumen bastante decente de cómo lvalues ​​y rvalues ​​trabajan en C++, junto con la forma en que pueden enlazar con referencias

La mayoría de los artículos que encontrará sobre las referencias de rvalue en C++ 0x le darán una idea de esto.

Cuestiones relacionadas