Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ : const references and initialization order

I am wondering if I am using the good approach in the following :

  • I want to construct a parent class (class A), this class should own an instance of a given "Foo" class
  • I want the parent class to own a child class member (class B) and this member should have a reference to the foo member of the parent class.

The code below seems to works, however I am wondering whether I was just "lucky" that the compiler was sympathetic enough.

For clarity, I added comment and my question in the comments below.

Thanks !

struct Foo
{
  std::string mValue;
};

class B
{
public:
  B(const Foo & foo) : mFoo_External(foo) {}
private:
  const Foo & mFoo_External; //this is an external reference to the member 
                             //(coming from A)
};

class A
{
public:
  //Here is the big question 
  //Shall I use : 
  //  A(const Foo & foo) : mFoo(foo), mB(mFoo) {}  
  //  or the declaration below
  A(const Foo & foo) : mFoo(foo), mB(foo) {}
private:
  //According to my understanding, the declaration 
  //order here *will* be important
  //(and I feel this is ugly)
  const Foo  mFoo;
  B mB;
};



void MyTest()
{
  std::auto_ptr<Foo> foo(new Foo());
  foo->mValue = "Hello";
  A a( *foo);
  foo.release();

  //At this point (after foo.release()), "a" is still OK 
  //(i.e A.mB.mFooExternal is not broken, although foo is now invalid)
  //
  //This is under Visual Studio 2005 : 
  //was I lucky ? Or is it correct C++ ?
}
like image 610
Pascal T. Avatar asked Jul 06 '26 05:07

Pascal T.


2 Answers

No, this is broken. Your mB will hold a reference to whatever you passed to the constructor of the A object, not to mFoo. Instead, you should say:

A(const Foo & foo) : mFoo(foo), mB(mFoo) { }

Note that mB is a copy of the constructor argument, and not a reference, so your MyTest function is fine.

like image 192
Kerrek SB Avatar answered Jul 09 '26 04:07

Kerrek SB


Since you want your B object to hold a reference to the parent's member, you must initialize mB with mFoo not foo.

You are correct that the order of the member variables is important, since it determines the order of the initialization. It might come as a surprise that the order of the initializers in the constructor does not determine the order they are called! See Constructor initialization-list evaluation order.

like image 38
Mark Ransom Avatar answered Jul 09 '26 04:07

Mark Ransom



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!