2011-01-18 11 views
7

In this question utente Happy Mittal sezione citazioni 12.2.5 di C++ 03 standard: Una temporanea legata a un membro di riferimento in ctor-inizializzatore di un costruttore (12.6.2) persiste fino a quando il costruttore esce.Qual è il punto di associazione temporanea a una dichiarazione di durata membro in C++ Standard?

Come può essere utile comunque? Voglio dire, una volta che il costruttore è uscito, il temporaneo viene distrutto, ma il riferimento rimane vincolato - ora a un oggetto già distrutto.

Qual è lo scopo di specificare con cura la durata temporanea se c'è ancora un riferimento ciondolante per l'intera vita dell'oggetto esterno? In quale scenario può essere utile questo comportamento?

+1

Mi stavo ponendo la stessa domanda. Si noti che la dicitura è invariata nel FCD C++ 0x (n3225), nella nota 12.2 [class.temporary] 5. –

risposta

7

Non è utile avere un membro di riferimento associato a un oggetto morto, ma è utile essere chiari che l'estensione di durata temporanea "normale" quando associata a un riferimento non si applica in questo caso.

Specifica inoltre l'estensione del tempo di vita temporaneo che si applica in modo particolare nell'inizializzatore di ctor: viene esteso alla fine del responsabile piuttosto che morire prima dell'esecuzione del corpo del ctor. Questo non sarebbe utile se non nelle classi "intelligenti" il cui punto è l'esecuzione del ctor, e questo tipo di (ab) uso è giustamente evitato.

Non conosco esempi del mondo reale di quest'ultimo, ma mi sembra che i distruttori non funzionino in base alle classi predefinite che erano "intelligenti" nella loro vita e in che modo venivano utilizzati. Questo ha avuto usi reali e came up in discussioni su come gestire la semantica predefinita di dtors in C++ 0x.

+0

Buon materiale in quel collegamento! +1 – jweyrich

2

In linguaggio D, il processo di costruzione può essere scritto liberamente in una certa misura. Tuttavia in C++, l'ordine di costruzione/inizializzazione è strettamente stipulato. Quindi, se l'inizializzazione della classe richiede alcuni calcoli costosi, un codice come a volte può essere valido come soluzione temporanea riluttante.

struct S { 
    Args const &r; 
    A a; 
    B b; 
    S(args....) 
    : r(expensive_func(args....)), a(r.for_a), b(r.for_b) {} 
}; 
+1

Rifattorizzato per evitare il membro di riferimento e il probabile sovraccarico risultante in ogni istanza: 'struct SDetails {A a; B b; SDetails (Args const & r): a (r.for_a), b (r.for_b) {}}; struct S: private SDetails {S (/ * args ... * /): SDetails (expensive_func (/ * args ... * /)) {}}; ' –

+1

Il refactoring diventa ancora più semplice/migliore con C++ 0x : 'struct S {A a; B b; S (/ * args ... * /): S (expensive_func (/ * args ... * /)) {} private: S (Args const & r): a (r.for_a), b (r.for_b) {}}; ' –

+0

Quindi, in altre parole, sebbene riconosca che l'inizializzazione a volte ha bisogno di soluzioni alternative in C++ 03, non utilizzerei mai un membro di riferimento in questo modo. –

1

È utile per gli autori di compilatori. Hanno già una logica in atto per distruggere i temporali legati alla fine di un ambito e l'uscita del costruttore è uno di questi punti. Con questa regola i compilatori possono riutilizzare quel punto per distruggere anche questi temporaries.

Si noti che lo standard dovrebbe davvero decidere per un certo periodo di tempo, e l'unico altro punto ragionevole sarebbe dopo l'elenco di inizializzatori ctor ma prima del corpo del ctor. Questo non è un punto in cui i provvisori verrebbero altrimenti distrutti, e potrebbe interferire con i blocchi try {} catch() delle funzioni-scope (che includono l'elenco di inizializzazione del ctor)

+0

Non tutte le espressioni di inizializzazione nell'inizializzatore di Ctor sono già un'espressione completa, poiché non sono la sottoespressione di un'altra espressione (C++ 03, §1.9p12)? Se è così, la distruzione di oggetti temporanei è già richiesta in quei punti. Ad esempio: 'struct A {int foo, bar; A(): foo (T(). M()), bar (T(). M()) {}}; 'I compilatori di compilatori potrebbero riutilizzarlo altrettanto facilmente (rendendo i compilatori più semplici in generale) a scapito di la lingua che consente ai membri di riferimento "sempre morti". –

+0

Beh, sarebbe stato possibile anche questo. Ma sarebbe utile? Suggerirei che i pericoli di un tale progetto superano i suoi benefici. – MSalters

+0

Non è questo il punto? I membri di riferimento ai temporali estesi per tutta la vita * non sono * utili, compresi quelli specificati attualmente - tranne nella misura in cui specificano * qualcosa * invece di lasciarlo completamente ambiguo, proprio come i riferimenti legati ai provvisori in una dichiarazione di ritorno. –

Problemi correlati