2011-11-15 6 views
7

Emette F~ ma mi aspettavo ~FNON il più importante const .. ma cos'è questo?

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

ho costruito questo come un controesempio per dimostrare che il più importante-const è un'eccezione piuttosto che una regola. Normalmente è scritto come

quando un riferimento const si lega ad una temporanea, poi la durata di tale temporanea è esteso a tutta la durata del rinvio

stavo cercando di illustrare che, anche se Foo() è temporaneo, il riferimento a _x restituito dall'operatore di conversione non lo è e il codice precedente non è sicuro.

Ma l'uscita sembra dimostrare che l'esempio è sicuro, la durata della temporanea Foo() si estende per l'esistenza di un riferimento const ad uno dei suoi membri.

È giusto? Dove è specificato lo standard?

+0

Tornando riferimenti è più spesso una cattiva idea di una buona. Questo è un buon esempio di questo. –

+0

@ R.MartinhoFernandes Quindi dichiari 'operator []' come ...? – curiousguy

risposta

6

La regola generale, per quanto riguarda i provvisori, è che la loro vita termina quando l'espressione completa fa parte dei fini (informalmente, quando si raggiunge lo ;).

12.2 oggetti temporanei

3/ [...] oggetti temporanei vengono distrutti come ultimo passaggio nella valutazione pieno-espressione (1.9) che (lessicale) contiene il punto in cui furono creati. Questo è vero anche se la valutazione termina con il lancio di un'eccezione. I calcoli del valore e gli effetti collaterali della distruzione di un oggetto temporaneo sono associati solo all'espressione completa, non a una sottoespressione specifica.

1

Questo perché il temporaneo sopravvive per l'intera durata della chiamata di funzione. Quando si esegue foo (Foo()); ecco cosa succede:

  1. temporanea Foo è contructed, quindi
  2. operator const int& viene chiamato sulla temporanea
  3. foo() è chiamato e questo emette F
  4. volta foo() rendimenti temporanea Foo è distrutta e questa uscita ~
+0

Elaborare: il codice è sicuro fintanto che 'foo' non memorizza il riferimento. –

1

Non c'è magia qui. Tutti gli argomenti della funzione vivono nell'ambito del chiamante, inclusi i provvisori. Il temporaneo Foo() è costruito nell'ambito del chiamante e distrutto alla fine della riga.

Quindi, qualunque sia la funzione foo()precedente a, gli argomenti in main() vengono eliminati.

0

Ma l'istanza di Foo qui si è sempre verificata fino a quando il punto e virgola non ha terminato l'istruzione in cui è stato creato. Il passaggio di un riferimento a un membro in una chiamata di funzione non ha modificato questo.

Prova:

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

contro

Foo const &ref = Foo(); // or function returning temp 
foo(ref); 
Problemi correlati