5

Il seguente è ben definito?Dipendenza circolare nell'elenco di inizializzazione del costruttore

class A; 
class B; 

// define A, which takes B& in constructor 
// define B, which takes A& in constructor 

class C 
{ 
    A a; 
    B b; 
public: 
    C() : a(b), b(a) { /* stuff with a and b */ } 
} 

Esempio completo a ideone.com.

È sicuro/ben definito fino a quando i costruttori per A e B non fanno nulla con i riferimenti che ottengono?

+1

Perché il downvote? Fammi sapere come posso migliorare la domanda. – Claudiu

+0

Non penso che il compilatore ti permetta di fare 'a (b)' perché quando 'a' viene inizializzato,' b' non è ancora inizializzato. – user3528438

+0

@ user3528438: Certamente, l'esempio ideone viene compilato ed eseguito. Ma è perché sono fortunato o perché è ben definito nello standard? – Claudiu

risposta

2

N4140 [class.cdtor]/1 legge:

Per un oggetto con un costruttore non banale, facendo riferimento a qualsiasi classe membro o base non statici dell'oggetto prima del costruttore comincia risultati di esecuzione nel comportamento indefinito. Per un oggetto con un distruttore non banale , facendo riferimento a qualsiasi membro non statico o classe base dell'oggetto dopo che il distruttore ha terminato i risultati di esecuzione in un comportamento non definito.

Sebbene questo passaggio non implichi che il comportamento sia altrimenti ben definito, il seguente esempio mostra che lo è. Ecco un estratto:

struct B : public A { int j; Y y; }; // non-trivial 
extern B bobj; 
B* pb = &bobj; // OK 

Quindi la risposta è: sì, il comportamento nel tuo caso è ben definita se non si fa riferimento ai membri o classi di base della b nel costruttore di A.

+0

Questo è abbastanza intuitivo. Quindi [l'esempio di user3528438] (https://ideone.com/V5uPyr) è un comportamento indefinito perché si accede a 'm_a.m_value' prima dell'esecuzione del costruttore di 'm_a'. Grazie per aver scavato il riferimento! – Claudiu

+0

@Claudiu Giusto, è sicuramente UB. –

+0

È possibile associare un * riferimento * a un oggetto che non è stato ancora creato? Ci sono differenze tra la semantica di puntatori e riferimenti. Ad esempio, 'int * p = nullptr; int & r = * p; 'è considerato UB, ma' int * r = &*p; 'è discutibilmente non UB (C lo consente esplicitamente, ad esempio). – dyp

Problemi correlati