2012-09-23 9 views
10

pensé referencias sólo se extienden la vida útil de los temporales de la vida útil de la propia referencia, pero la salida del siguiente fragmento parece contradictoria:¿Cuál es la duración de un argumento predeterminado vinculado temporalmente a un parámetro de referencia?

#include <iostream> 

struct X{ ~X(){ std::cout << "Goodbye, cruel world!\n"; } }; 

X const& f(X const& x = X()){ 
    std::cout << "Inside f()\n"; 
    return x; 
} 

void g(X const& x){ 
    std::cout << "Inside g()\n"; 
} 

int main(){ 
    g(f()); 
} 

Live example. Salida:

Inside f() 
Inside g() 
Goodbye, cruel world! 

por lo que parece el temporal se destruye después de que se llama g() ... ¿qué da?

+0

Es normalmente se considera hostil para no dejar una explicación cuando downvoting. – Xeo

+0

Mi conjetura es que el infractor accidentalmente presionó el botón de abajo hacia abajo cuando en realidad querían presionar el botón de reenvío (mirando el total de los votos por su respuesta y la pregunta también apoya esta teoría). ¡Pero quién sabe! –

+0

@Jesse: Buena teoría, pero la respuesta tenía más votos positivos que la pregunta antes de que llegara el voto en baja. :) – Xeo

Respuesta

13

La norma se ocupa de esto en un caso especial en §12.2 [class.temporary]:

p4 Hay dos contextos en los que los temporales se destruyen en un punto diferente que el final de la expresión completa. [...]

p5 El segundo contexto es cuando una referencia está vinculada a un temporal. El temporal a la que se une la referencia o el temporal que es el objeto completo de un subobjeto a la que la referencia está obligado persiste durante toda la vida de la referencia excepto:

  • A temporal unido a un parámetro de referencia en una función call (5.2.2) persiste hasta la finalización de la expresión completa que contiene la llamada.

La norma también tiene una nota práctica de expresiones completas y la evaluación de sus subexpresiones con respecto a los parámetros por defecto en §1.9 [intro.execution] p11:

[Nota: La evaluación de un completo La expresión puede incluir la evaluación de subexpresiones que no son léxicamente parte de la expresión completa. Por ejemplo, las subexpresiones implicadas en la evaluación de los argumentos predeterminados (8.3.6) se consideran creados en la expresión que llama a la función, no la expresión que define el argumento predeterminado. -fin nota]

1

Interesante, 1. (No pretendo competir con tu buena auto respuesta aquí). Solo una nota al margen para cualquier persona interesada. Si quieres un efecto similar pero permitiendo no constante que podría utilizar la semántica movimiento:

#include <iostream> 

struct X{ 
    ~X(){ std::cout << "Goodbye, cruel world!\n"; } 
    X(X && x){ std::cout << "moved "; } 
    X(){} 
}; 

X f(X x = X()){ 
    std::cout << "Inside f()\n"; 
    return x; 
} 

void g(X x){ 
    std::cout << "Inside g()\n"; 
} 

int main(){ 
    g(f()); 
} 

da

Inside f() 
moved Inside g() 
Goodbye, cruel world! 
Goodbye, cruel world! 
+0

También puedes usar 'X &&' y devolver 'std :: move (x)'. :) – Xeo

+0

@Giovanni su declaración no está clara si no está mal. –

+1

@Xeo "return std :: move (x)" debe evitarse en este caso, ver más detalles, por ejemplo, en https://stackoverflow.com/questions/14856344/when-should-stdmove-be-used-on-a -function-return-value –

Cuestiones relacionadas