2010-06-14 15 views
17

¿Se garantiza que un temporal creado como parte de un argumento de una llamada de función se mantendrá hasta que la función llamada finalice, incluso si el temporal no se pasa directamente a la función?¿Cuándo se crean los temporales creados como parte de una llamada de función destruida?

hay prácticamente ninguna posibilidad de que era coherente, así que aquí está un ejemplo:

class A { 
public: 
    A(int x) : x(x) {printf("Constructed A(%d)\n", x);} 
    ~A() {printf("Destroyed A\n");} 

    int x; 
    int* y() {return &x;} 
}; 

void foo(int* bar) { 
    printf("foo(): %d\n", *bar); 
} 

int main(int argc, char** argv) { 
    foo(A(4).y()); 
} 

Si A(4) fueron pasados ​​directamente a foo sería definitivamente no será destruido hasta después de la llamada foo terminó, pero en lugar de eso estoy llamando un método en el temporal y perder cualquier referencia a él. Instintivamente pensaba que el A temporal se destruiría antes de que foo incluso se inicie, pero probar con GCC 4.3.4 muestra que no es así; la salida es:

construyó una (4)
foo(): 4
destruyó un

La pregunta es, es el comportamiento de GCC garantizada por la especificación? ¿O se permite a un compilador destruir el A temporal antes de la llamada al foo, invalidando el puntero a su miembro que estoy usando?

Respuesta

17

Existen objetos temporales hasta el final de la expresión completa en la que se crearon.

En el ejemplo, el objeto creado por AA(4) existirá al menos hasta que la expresión termina justo después del regreso de la llamada a foo().

Este comportamiento está garantizado por la norma idioma:

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 (C++ 03 §12.2/3).

El tiempo de vida de la temporal se puede extender mediante la unión una referencia a él (en cuyo caso su vida útil se prolonga hasta el final de la vida útil de la referencia), o mediante el uso como un inicializador en inicializador de un constructor lista (en cuyo caso, su duración se extiende hasta que el objeto que se está construyendo esté completamente construido).

+0

impresionante Gracias a ti y Jerry para encontrar la referencia en la especificación, que tenía problemas para encontrarlo –

2

El temporal dura hasta el final de la expresión de la que forma parte, que en este caso es una llamada a función.

-1

El tiempo de vida de su objeto temp A(4) va a durar el tiempo suficiente para llamar y()

La memoria indicada en el retorno de y() no es fiable, dependiendo de rosca y las asignaciones puede ser reasignado y el valor cambiado antes de la llame al foo() hace uso de él.

+0

Hmmm , al parecer, MSVC me está dando una respuesta no estándar, es bueno aprender el estándar. –

5

§12.2/3: "Los objetos temporales se destruyen como el último paso en la evaluación de la expresión completa (1.9) que (léxicamente) contiene el punto donde se crearon."

OIA, estás a salvo -.. A el objeto no debe ser destruida hasta después de foo vuelve

Cuestiones relacionadas