Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to bind a reference to a not yet constructed object in C++?

Tags:

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?

like image 701
sharptooth Avatar asked Jan 27 '11 11:01

sharptooth


1 Answers

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.

like image 96
Fred Nurk Avatar answered Dec 25 '22 14:12

Fred Nurk