Consider this code sample:
class Base {
public:
Base( string& _object ) : object( _object ) {}
private:
string& object;
};
class Derived: public Base {
public:
Derived() : Base( object ) {}
private:
string object;
};
Obviously first Base
is constructed and it is passed a reference to a not yet constructed object.
Memory is allocated for the whole Derived
object, so Derived::object
is in legally accessible memory, just its constructor has not run. Base::Base()
doesn't call any methods of passed object, only stores the reference. It works in Visual C++ 9.
Is it safe according to C++ Standard?
It is safe, as long as you don't "use" the reference before object is constructed. You can use the base-from-member idiom to move object into a (private) base class which comes before Base, and thus be constructed before Base, if you need to change the construction order:
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:
…before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any lvalue which refers to the original object may be used but only in limited ways. Such an lvalue refers to allocated storage (3.7.3.2), and using the properties of the lvalue which do not depend on its value is well-defined. …
In a nutshell: don't access any members, methods, or pass it to anything that does. You can take its address and bind references to it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With