Is it safe to use the "this" pointer in an initialization list?

C++InitializationThis

C++ Problem Overview


I have two classes with a parent-child relationship (the Parent class "has-a" Child class), and the Child class has a pointer back to the Parent. It would be nice to initialize the parent pointer upon construction of the child, as follows:

class Child;
class Parent;

class Child
{
public:
 Child (Parent* parent_ptr_) : parent_ptr(parent_ptr_) {};

private:
 Parent* parent_ptr;
};

class Parent
{
public:
    Parent() : child(this) {};

private:
    Child child;
}

Now, I know people recommend not using this in initialization list, and C++ FAQ says I'm gonna get a compiler warning (BTW, on VS2010, I don't get a warning), but I really like this better then calling some set function in Parent's constructor. My questions are:

  • Is the parent this pointer well-defined when the Child object is being created?
  • If so, why is it considered bad practice to use it as above?

Thanks,

Boaz

EDIT: Thanks Timbo, it is indeed a duplicate (huh, I even chose the same class names). So lets get some added value: how about references? Is it possible / safe to do the following? :

class Child
{
public:
 Child (Parent& parnet_ptr_) : parent_ptr(parent_ptr_) {};

private:
 Parent* parent_ptr;
};

class Parent
{
public:
    Parent() : child(*this) {};

private:
    Child child;
}

C++ Solutions


Solution 1 - C++

Yes. It's safe to use this pointer in initialization-list as long as it's not being used to access uninitialized members or virtual functions, directly or indirectly, as the object is not yet fully constructed. The object child can store the this pointer of Parent for later use!

Solution 2 - C++

The parent this pointer, in "pointer terms", is well-defined (otherwise how would the parent constructor know on which instance is it operating?), but:

  • the fields that are declared after the Child object aren't initialized yet;
  • the code in the constructor hasn't run yet;
  • also, the usual warnings about using virtual members from the constructor apply1.

So, the parent object in general is still in an inconsistent state; everything the child object will do on construction on the parent object, will be done on a half-constructed object, and this in general isn't a good thing (e.g. if it calls "normal" methods - that rely on the fact that the object is fully constructed - you may get in "impossible" code paths).

Still, if all the child object do with the parent pointer in its constructor is to store it to be use it later (=> when it will be actually constructed), there's nothing wrong with it.


  1. I.e., virtual dispatch doesn't work in constructors, because the vtable hasn't been updated yet by the derived class constructor. See e.g. here.

Solution 3 - C++

The behaviour is well-defined so long as you don't attempt to dereference the pointer until after the Parent object has been completely constructed (as @Sergey says in a comment below, if the object being constructed is actually derived from Parent, then all of its constructors must have completed).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbavazaView Question on Stackoverflow
Solution 1 - C++NawazView Answer on Stackoverflow
Solution 2 - C++Matteo ItaliaView Answer on Stackoverflow
Solution 3 - C++Oliver CharlesworthView Answer on Stackoverflow