Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

passing this from constructor initializer list

Tags:

c++

Are there any issues when passing 'this' to another object in the initializer list in the following code?

class Callback { public: virtual void DoCallback() = 0; }; 

class B
{
    Callback& cb;
public:
    B(Callback& callback) : cb(callback) {}
    void StartThread();

    static void Thread() 
    {
        while (!Shutdown())
        {
            WaitForSomething();
            cb.DoCallback();
        }
     }
};

class A : public Callback
{
    B b;
public:
    A() : b(*this) {b.StartThread();}
    void DoCallback() {} 
};

If it is unsafe to do that, what's the best alternative?

like image 248
markh44 Avatar asked May 15 '09 15:05

markh44


People also ask

Does initializer list call constructor?

An initialization list can be used to explicitly call a constructor that takes arguments for a data member that is an object of another class (see the employee constructor example above). In a derived class constructor, an initialization list can be used to explicitly call a base class constructor that takes arguments.

What is a constructor initializer list?

Initializer List is used in initializing the data members of a class. The list of members to be initialized is indicated with constructor as a comma-separated list followed by a colon. Following is an example that uses the initializer list to initialize x and y of Point class.

Does initializer list run before constructor?

As already answered, initialization lists get completely executed before entering the constructor block. So it is completely safe to use (initialized) members in the constructor body.

When should a constructor use an initializer?

Initialization lists allow you to choose which constructor is called and what arguments that constructor receives. If you have a reference or a const field, or if one of the classes used does not have a default constructor, you must use an initialization list.


2 Answers

If the other class just stores the pointer/reference, like in your case, it is safe. But you have to be sure that the constructors/functions you pass this to are not trying to access the referenced object before A's constructor finishes. The A object is not fully constructed yet and calling methods of A and accessing properties might lead to undefined results.

like image 133
sth Avatar answered Nov 10 '22 17:11

sth


If you are extremely careful this will work fine. You will get into a lot of trouble if you start calling virtual methods or using methods which depend on other objects in the type. But if you're just setting a reference this should work fine.

A safer (but not completely safe) alternative is to set b later on once the constructor is completed. This won't eliminate vtable issues but will remove problems like accessing other member variables before they are constructed.

class A : public Callback {
  std::auto_ptr<B> spB;
public:
  A() {
    spB.reset(new B(this));
    spB->StartThread();
  }
};
like image 36
JaredPar Avatar answered Nov 10 '22 17:11

JaredPar