2011-11-15 13 views
7

Esto genera F~ pero esperaba ~FNO es la tecnología más importante ... ¿pero qué es esto?

#include <iostream> 

struct Foo { 
    int _x; 
    operator const int &() const {return _x;} 
    ~ Foo() {std :: cout << "~";} 
}; 

void foo (const int &) 
{ 
    std :: cout << "F"; 
} 

int main() 
{ 
    foo (Foo()); 
} 

construí esto como un contraejemplo para demostrar que la const más importante es la excepción y no la regla. Normalmente se escribe como

cuando una referencia const se une a un temporal, entonces el tiempo de vida de que temporal se extiende a toda la vida útil de la referencia

yo estaba tratando de ilustrar que, aunque Foo() es una temporal, la referencia a _x devuelta por el operador de conversión no lo es, y que el código anterior no es seguro.

Pero la salida parece probar que el ejemplo es segura, la vida útil del temporal Foo() se extiende por la existencia de una referencia constante a uno de sus miembros.

¿Es esto correcto? ¿Dónde está especificado en el estándar?

+0

Volviendo referencias es más a menudo una mala idea que uno bueno. Este es un buen ejemplo de eso. –

+0

@ R.MartinhoFernandes ¿Entonces declaras 'operador []' como ...? – curiousguy

Respuesta

6

La regla general, con respecto a los temporales, es que su vida termina cuando finaliza la expresión completa de la que forman parte (informalmente, al llegar al ;).

12.2 objetos temporales

3/ [...] objetos temporales se destruyen como el último paso en la evaluación de la expresión completa (1.9) que (léxico) contiene el punto en el que fueron creados. Esto es cierto incluso si esa evaluación termina arrojando una excepción. Los cálculos de valor y los efectos secundarios de destruir un objeto temporal están asociados solo con la expresión completa, no con ninguna subexpresión específica.

1

Eso es porque el temporal sobrevive durante toda la duración de la llamada a la función. Cuando lo haga foo (Foo()); esto es lo que sucede:

  1. temporal Foo contructed, entonces
  2. operator const int& se llama en el temporal
  3. foo() se llama y esto da salida a F
  4. vez foo() retornos temporales Foo es destruida y esto salidas ~
+0

Elaborar: el código es seguro siempre que 'foo' no almacene la referencia. –

1

No hay magia aquí. Todos los argumentos de funciones viven en el alcance de la persona que llama, incluidos los temporales. El Foo() temporal se construye en el alcance de la persona que llama y se destruye al final de la línea.

Así que cualquiera que sea la función foo() hace sucede antes sus argumentos en main() se destruyen.

0

Pero su instancia Foo aquí siempre va a vivir hasta que el punto y coma finalice la instrucción en la que se creó. Pasar una referencia a un miembro a una llamada de función no cambió eso.

Probar:

int const &ref = Foo(); 
foo(ref); 

frente

Foo const &ref = Foo(); // or function returning temp 
foo(ref); 
Cuestiones relacionadas