2011-01-27 11 views
20

Considerate questo esempio del codice:È sicuro associare un riferimento a un oggetto non ancora costruito in C++?

class Base { 
public: 
    Base(string& _object) : object(_object) {} 
private: 
    string& object; 
}; 

class Derived: public Base { 
public: 
    Derived() : Base(object) {} 
private: 
    string object; 
}; 

Ovviamente prima Base è costruita e si passa un riferimento a un oggetto non ancora costruito.

La memoria è allocata per l'intero oggetto Derived, quindi Derived::object è nella memoria legalmente accessibile, solo il suo costruttore non è stato eseguito. Base::Base() non chiama alcun metodo dell'oggetto passato, memorizza solo il riferimento. Funziona in Visual C++ 9.

È sicuro secondo lo standard C++?

+0

Buona domanda. L'ho fatto in uno dei miei progetti, e sta funzionando bene; mai visto alcun problema. Ma mi piacerebbe sapere se è "sicuro". – Nawaz

risposta

19

È sicuro, purché non si "usi" il riferimento prima che l'oggetto sia costruito. È possibile utilizzare il base-from-member idiom per spostare oggetto in una classe di base (privato), che viene prima di base, e quindi essere costruiti prima base, se è necessario modificare l'ordine di costruzione:

struct Base { 
    Base(string &ref) { 
    cout << "imagine the ctor uses the ref: " << ref; 
    } 
}; 

struct DerivedDetail { 
    DerivedDetail(string const &x) : object (x) {} 
    string object; 
}; 

struct Derived : private DerivedDetail, Base { 
    Derived() : DerivedDetail("foobar"), Base(object) {} 
    // In particular, note you can still use this->object and just 
    // ignore that it is from a base, yet this->object is still private 
    // within Derived. 
}; 

C++ 03 §3.8p6:

... prima che il ciclo di vita di un oggetto è iniziata, ma dopo l'archiviazione, che l'oggetto occuperanno è stata assegnata o, dopo il ciclo di vita di un oggetto è finita e prima della memorizzazione che l'oggetto è occupata riutilizzato o rilasciato, qualsiasi lvalue che si riferisce all'oggetto originale può essere usato ma solo in modi limitati. Tale valore si riferisce alla memoria allocata (3.7.3.2) e l'utilizzo delle proprietà del lvalue che non dipendono dal valore dipende dal suo valore. ...

In breve: non accedere a membri, metodi o passarlo a qualsiasi cosa che faccia. Puoi prendere il suo indirizzo e legare i riferimenti ad esso.

+0

+1 per la citazione dallo standard! – Nawaz

Problemi correlati