开发者

When is "this" pointer initialized in C++?

Hi I have a question about this pointer, when an object is constructed, when it is initialized? Which means, when can I use it? The virtual table is constructed in the constructor, is the same with this pointer?

For example, I开发者_开发技巧 have a code like this. The output is 8. Does it mean that before the constructor is entered, this pointer is already initialized?

class A{
   public:
     A() { cout<<sizeof(*this);}
     int i;
     int *p; 
};

int main() {      
    A a; 
}

If it is true, what else would happen before the constructor is entered ?

If it is not true, when is the this pointer initialized ?


The this pointer isn't a member of the object or class - it's an implicit parameter to the method that you call. As such it's passed in much like any other parameter - except that you don't directly ask for it.

In your example above, the constructor is a special method, which is in turn a special kind of function. When you construct the object, the compiler allocates memory for it (in this case on the stack, as a is a local variable in the main function. Then it automatically calls the constructor to initialise the object.

As part of calling the constructor, the implicit parameter this - a pointer to your object - is passed in as a parameter.

In a method with the following signature...

void MyMethod (const int* p) const;

there are actually two parameters, both pointers. There's the explicit parameter p and the implicit parameter this. The const at the end of the line specifies that this is a const pointer, much as the earlier one specifies that p is a const pointer. The need for that special syntax only exists because this is passed implicitly, so you can't specify const-ness in the normal way as with other parameters.

A "static" method doesn't have the implicit "this" parameter, and cannot directly access the object members either - there may not be a particular object associated with the call. It is basically a standard function rather than a method, except with access to private members (providing it can find an object to access).

As Steve Fallows points out, sizeof (this) is known at compile-time, because it is a pointer type and all pointers (*1) have the same sizeof value. The "8" you see implies you are compiling for a 64-bit platform. this is usable at this point - it points to valid memory, and all the members have completed their constructor calls. However, it isn't necessarily fully initialised - you are still in the constructor call after all.

EDIT

*1 - strictly, that may not be true - but the compiler knows what type of pointer it's dealing with here even though the value isn't known until runtime.


The this pointer is not stored. When the constructor is called for an object that occupies a specific memory location, that location is passed as a parameter to the constructor and other member functions.

If this would be stored inside the object, how to retrieve that pointer? Right, you would again need the this pointer :)


sizeof(*this) is known at compile time. So the cout statement reveals nothing about the initialization of this.

Given that the constructor can immediately begin accessing members of the object, clearly this is initialized before the constructor begins.

What else happens before the constructor? Well could be anything. I don't think the standard limits what a compiler could do. Maybe you should specify anything you're thinking might happen.


The virtual table is constructed in the constructor, is the same with this pointer?

The virtual table is NOT constructed in the constructor.
Typically, a single global v-table is shared by all instances of the same class, and each individual class has its own global v-table.
The v-table is known at compile-time, and "constructed" at program load time.

The this pointer is "constructed" (I think "allocated" is a better term) at allocation time, that is, after the global new operator is called, and before the constructor is entered.

In cases where the object is stack-allocated instead of heap-allocated, global new is not called, but this is still available as a result of allocating stack-space, which is just before the constructor is entered.

The instance vptr is assigned after the object's memory is allocated, and just before the constructor is called.


Does it mean that before the constructor is entered, the this pointer is already initialized?

Yes, the value of the this pointer is known before the constructor is even called. This value is available via the this keyword inside constructors, constructor initialization lists, destructors, member methods. The this keyword behaves on the surface as a method variable (of pointer type) but is not one; it typically sits in a register (ecx on x86 platforms) and you typically won't be able to compile code like &this.

What else would happen before the constructor is entered

At least as far as the this pointer is concerned, the first thing that happens (unless using placement new) is the allocation of memory ultimately pointed to by this, be it on the stack (like in your example) or on the heap (using new.) At this point the this pointer is known. Then, either default constructors or explicitly specified constructors (via constructor initialization lists) are then called on the base classes (if any) and on your class non-POD member variables (if any). The class vtable pointer is also set before this point if your class contains virtual methods or destructor. Then, your class constructor body, if any, is invoked. (Constructor are called recursively, i.e. when a base class' constructor is called, the latter's base class constructors are called followed by non-POD member constructors, with the base class' vtable pointer being set, followed by the class' constructor body.)


The this pointer is the first argument to every call of the class, including the constructor.

When a class method is called, the address of the class is pushed onto the stack last (assuming cdecl calling convention here). This is read back into a register to use as the this pointer.

Constructors are in fact called as if they were ordinary member functions.

You cannot have a virtual constructor because the constructor is responsible for setting the vtable member.


As nobugz already pointed out, your example doesn't really mean much -- sizeof yields its results based on the type of the object you pass to it. It does not evaluate its operand at run-time.

That said, yes, this is initialized before entry to the ctor. Basically, the compiler allocates space for the object (on the stack if the object has automatic storage duration, or using ::operator new if it has dynamic storage duration). Upon entry to the ctor, the ctors for base classes (if any) have already run to completion. When your ctor is called, this gives the address of the memory that was allocated for the object.


this starts pointing to the current object and all members and base classes have been initialized before you enter the constructor body.

Therefore, you can hand out pointer to this in the initialization list, but the receiver should do nothing else other than storing it, because the pointed-at instance may not be fully constructed at the time.

#include <iostream>

class B;

class A
{
    B* b_ptr;
public:
    A(B* b);
};

class B
{
    A a;
    int i;
public:
    B(): a(this), i(10) {}
    void foo() const { std::cout << "My value is " << i << '\n'; }
};

A::A(B* b):
    b_ptr(b) //Ok to store
{
    b_ptr->foo(); //not OK to use, will access initialized member
}

int main()
{
    B b;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜