2012-09-23 6 views
10

ho pensato riferimenti riguardano unicamente la durata di provvisori per la durata del riferimento stesso, ma l'uscita del seguente frammento sembra contraddittoria:Qual è la durata di un argomento predefinito temporaneamente associato a un parametro di riferimento?

#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. uscita:

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

così sembra la temporaneo viene distrutto dopo che g() viene chiamato ... cosa dà?

+0

E 'normalmente considerato ostile per non lasciare una spiegazione quando downvoting. – Xeo

+0

La mia ipotesi è che il downvoter colpisca accidentalmente il pulsante downvote quando in realtà volevano premere il pulsante di upvote (guardando i voti totali per la risposta e la domanda supporta anche questa teoria). Ma chi lo sa! –

+0

@Jesse: Bella teoria, ma la risposta ha avuto più uptotes rispetto alla domanda prima che arrivasse il downvote. :) – Xeo

risposta

13

Lo standard gestisce questo in un caso particolare in §12.2 [class.temporary]:

p4 Ci sono due contesti in cui provvisori vengono distrutti in un punto diverso rispetto all'estremità del pieno-espressione. [...]

p5 Il secondo contesto è quando un riferimento è associato a un temporaneo. La temporanea in cui è vincolato il riferimento o la temporanea che è l'oggetto completo di un oggetto secondario per cui il riferimento è vincolato persiste per tutta la durata del riferimento eccetto:

  • Un temporaneo legato a un parametro di riferimento in una funzione chiamare (5.2.2) fino a completamento dell'espressione completa contenente la chiamata.

La norma dispone anche di una nota a portata di mano sul full-espressioni e la valutazione dei loro sottoespressioni per quanto riguarda i parametri di default in §1.9 [intro.execution] p11:

[Nota: La valutazione di un full- espressione può includere la valutazione di sottoespressioni che non sono lessicamente parte della piena espressione. Ad esempio, le sottoespressioni coinvolte nella valutazione degli argomenti predefiniti di (8.3.6) vengono considerate create nell'espressione che chiama la funzione, non l'espressione che definisce l'argomento predefinito. -end note]

1

Interessante, +1. (Non intendo competere con la tua bella auto risposta qui). Solo una nota a margine per chiunque sia interessato. Se si desidera un effetto simile, ma che consente non-const si potrebbe usare la semantica move:

#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()); 
} 

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

Puoi anche usare 'X &&' e restituire 'std :: move (x)'. :) – Xeo

+0

@Giovanni la tua affermazione non è chiara se non errata. –

+1

@Xeo "return std: move (x)" dovrebbe essere evitato in questo caso, vedere maggiori dettagli ad esempio su https://stackoverflow.com/questions/14856344/when-should-stdmove-be-used-on-a -funzione-ritorno-value –