views:

451

answers:

4

Can I pass "this" to a function as a pointer, from within the class constructor, and use it to point at the object's members before the constructor returns?

Is it safe to do this, so long as the accessed members are properly initialized before the function call?

As an example:

#include <iostream>

class Stuff
{
public:
    static void print_number(void *param)
    {
     std::cout << reinterpret_cast<Stuff*>(param)->number;
    }

    int number;

    Stuff(int number_)
     : number(number_)
    {
     print_number(this);
    }
};

void main() {
    Stuff stuff(12345);
}

I thought this wouldn't work, but it seems to. Is this standard behavior, or just undefined behavior going my way?

+7  A: 

When you instantiate an object in C++, the code in the constructor is the last thing executed. All other initialization, including superclass initialization, superclass constructor execution, and memory allocation happens beforehand. The code in the constructor is really just to perform additional initialization once the object is constructed. So it is perfectly valid to use a "this" pointer in a class' constructor and assume that it points to a completely constructed object.

Of course, you still need to beware of uninitialized member variables, if you haven't already initialized them in your constructor code.

MattK
Half true. Think twice before using this in a constructor, especially when something could derive from the class. In that case you work with a partially constructed class and calling virtuals is, afaik, undefined. Same is true for general 'class state': the derived constructor may still modify it.
+2  A: 

You can find a good answer to this here.

All inherited members and members of the calling class are guaranteed to have been constructed at the start of the constructor's code execution and so can be referenced safely within it.

The main gotcha is that you should not call virtual functions on this. Most times I've tried this it just ends up calling the base class's function, but I believe the standard says the result is undefined.

Andy
The link appearst o be broken...
Omar Kooheji
It's undefined for pure virtual functions (that don't yet have a definition).
Richard Corden
A: 

Andy, I think you're wrong about the undefined part of the standard.

When you're in the constructor, "this" is a pointer to an object whose type is the base class of the object you're creating, which means that virtual functions partially implemented in the base class will be called and the pointers in the virtual table won't be followed.

More info in the C++ Faq Lite...

random
Wrong: When you enter Derived::Derived, this-> already points to a Derived object. This differs from e.g. Java, where this. can point to the MostDerived object. In neither language will this-> point to "a" Base class in Derived's constructor. Also, with MI, which Base would this point to?
MSalters
A: 

As a side-note on the presented code, I would instead templatize the void*:

class Stuff
{
public:
    template <typename T>
    static void print_number(const T& t)
    {
        std::cout << t.number;
    }

    int number;

    Stuff(int number_)
    : number(number_)
    {
        print_number(*this);
    }
};

Then you'd get a compile error if the type of t doesn't have a number member.

Johann Gerell