Is It Safe to Use the "This" Pointer in an Initialization List

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

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!

Using this pointer in an initialization list

test(int _a) : this->bse(24) , a(_a) { ... }

is not valid since only member variables and base classes can be initialized in the initializer list. Members of base classes cannot be initialized there.

You have to initialize and/or set the value of the bse member of the base class using other ways.

  1. Provide a constructor in the base class that takes an int. Then, you can use:

    test(int _a) : base(24) , a(_a) { ... }
  2. Set the value in the body of test().

    test(int _a) : a(_a) { bse = 24; ... }

Is it safe to pass this pointer in the initializer list in C++?

If the first variable, in ThirdClass's constructor is not used, only stored for future use, then this is safe and well defined. If you attempt to use/dereference the pointer in the constructor, then it would be undefined behaviour, since the FirstClass object has not been constructed yet.

In your example, you wrote:

register for some events here.

that events will call someMethod and someMethod is calling FirstClass's method, before initializer list of FirstClass gets executed.

Since this means that the object's method will be called, then this is likely not valid, and will be Undefined Behaviour, since you cannot call method of an uninitialized object (unless all members that function relies upon are initialized).

passing this from constructor initializer list

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();
}
};

using this pointer in initializer list

The code is ambiguous.

For constructing the C base of F, the context is direct-initialization, so 13.3.1.3 applies:

c++11

13.3.1.3 Initialization by constructor [over.match.ctor]


For direct-initialization, the candidate
functions are all the constructors of the class of the object being initialized.

The implicitly-declared copy constructor is included, per 12.8:8.

The candidates for the constructor of C are C(T &) and (the default copy constructor) C(const C &), by parameter list (F). In both cases we have a reference binding (13.3.3.1.4) followed by a derived-to-base Conversion (13.3.3.1), with an additional cv-qualification adjustment in the latter case, giving overall rank of Conversion in both cases.

Since C and T are both base classes of F, but are distinct types and neither is a base class of the other, none of the clauses in 13.3.3.2:3 nor 13.3.3.2:4 apply and conversion sequences are indistinguishable.

Indeed, gcc-4.5.1 rejects the code with:

prog.cpp: In constructor 'F::F(const T&)':
prog.cpp:20:34: error: call of overloaded 'C(F&)' is ambiguous
prog.cpp:9:5: note: candidates are: C::C(T&)
prog.cpp:7:1: note: C::C(const C&)

C++: Should I initialize pointer members that are assigned to in the constructor body to NULL?

Generally you only assign it once, in the initialization list or the body, unless the body initialization may or may not happen, or has prerequisite code:

MyClass::MyClass() 
{
//this code must happen first
// _now_ max is known
something_ = new Something(max);
}

MyClass::MyClass()
{
if (max)
something_ = new Something(max);
else
something_ = NULL;
}

MyClass::MyClass()
: something_(new Something())
//as pointed out in the comments, use smart pointers
{
}

Member initializer list, pointer initialization without argument

Empty () initializer stands for default-initialization in C++98 and for value-initialization in C++03 and later. For scalar types (including pointers) value-initialization/default-initialization leads to zero-initialization.

Which means that in your case m() and m(nullptr) will have exactly the same effect: in both cases m is initialized as a null pointer. In C++ it was like that since the beginning of standardized times.

C++ using this pointer in constructors

The consequence is that the thread can start and code will start executing a not yet fully initialized object. Which is bad enough in itself.

If you are considering that 'well, it will be the last sentence in the constructor, it will be just about as constructed as it gets...' think again: you might derive from that class, and the derived object will not be constructed.

The compiler may want to play with your code around and decide that it will reorder instructions and it might actually pass the this pointer before executing any other part of the code... multithreading is tricky



Related Topics



Leave a reply



Submit