2014-10-09 11 views
6

Che cosa so

So che restituire un riferimento const di un oggetto temporaneo è ok! (Come in questo esempio :)return const riferimento della sottoclasse

class A { 
public: 
    virtual const A& clone() { return (A()); } 
    virtual std::string name() const { return ("A"); } 
}; 

Returning temporary object and binding to const reference

Ma!

Se vorrei farlo, è ancora corretto:

class B : public A { 
public: 
    virtual const A& clone() { return (B()); } 
    virtual std::string name() const { return ("B"); } 
}; 

Vorrei pensare di sì, ma in tempo di esecuzione, l'oggetto restituito è ancora considerato come un un oggetto (come in questo esempio:)

main.cpp

#include <iostream> 
#include <string> 
int main() { 
    B bb; 
    A* aa = &bb; 

    std::cout << aa->clone().name() << std::endl; 
} 

uscita

valgrind ./a.out 
==14106== Use of uninitialised value of size 8 
==14106== at 0x401BF9: main (main.cpp:8) 
==14106== Uninitialised value was created by a stack allocation 
==14106== at 0x401BF2: main (main.cpp:8) 
B 

Si tratta di un B .. yay .. ma questo avvertimento è abbastanza horrifing ....

Modifica

Grazie a te so vedere il mio errore ... ma vorrei sapere alcune altre cose a proposito ...

Quando viene eseguito, cosa accade esattamente nello stack?

+0

@Chris Drew ... errrh Non capisco – CollioTV

+3

"So che restituire un riferimento const di un oggetto temporaneo è ok!" No, non lo è. –

+2

http://stackoverflow.com/questions/11560339/returning-temporary-object-and-binding-to-const-reference "Questa è una funzionalità in C++ Il codice è valido e fa esattamente ciò che sembra fare.", "C++ specifica deliberatamente che legare un oggetto temporaneo a un riferimento a const sullo stack allunga la vita del temporaneo alla durata del riferimento stesso" – CollioTV

risposta

12

Unire un riferimento a un temporaneo estende la durata del temporaneo ... tranne quando non lo fa. §12.2 [class.temporary]/p5, corsivo:

Il temporaneo a cui è vincolato il riferimento o la temporanea che è l'oggetto completo di un oggetto secondario a cui è vincolato il riferimento persiste per la durata del riferimento eccetto:

  • un temporaneo legato ad un organo di riferimento a un costruttore ctor-inizializzatore (12.6.2) persiste fino le uscite costruttore.
  • Un collegamento temporaneo a un parametro di riferimento in una chiamata di funzione (5.2.2) persiste fino al completamento della espressione completa contenente la chiamata.
  • La durata di un vincolo temporaneo al valore restituito in una dichiarazione di ritorno funzione (6.6.3) non è stata estesa; il temporaneo è distrutto alla fine della espressione intera nell'istruzione di reso.
  • Un temporaneo legato ad un riferimento in un nuovo -inizializzatore (5.3.4) persiste fino al completamento del full-espressione contenente la nuovo-inizializzatore.

Il caso in questione si è collegato (std::string foo(); const std::string & s = foo();) è OK; la durata del temporaneo restituito da foo() viene estesa fino alla fine della vita di s. Nel codice, il temporaneo è associato al valore restituito e, per il terzo punto puntato sopra, la sua durata non viene estesa e la funzione restituisce un riferimento ciondolante.

In genere, le funzioni clone() devono restituire un puntatore a una copia allocata all'heap.

+0

E ho cambiato il mio codice per farlo! Grazie! – CollioTV

+0

@ T.C. Quindi, cosa succede se ho un metodo che restituisce un riferimento const a una sottoclasse (o membro var) di * this? Il chiamante deve essere consapevole del fatto che il riferimento non sopravvive all'oggetto sul quale è stato chiamato il metodo; e se quell'oggetto è temporaneo, la lingua non estenderà la sua durata da queste regole, poiché il riferimento non viene preso nel codice chiamante, ma nel metodo. Corretta? – greggo