C++ 构造函数与this指针

         之前一直理解的构造函数的参数里没有this指针,因为此时对象还没生成,其他非static成员函数才有this指针,因为当它们被调用时对象已经生成了。然而这样理解是错误的,构造函数参数里也是有this指针的,但这个this指针只是指向了一个内存地址,这个内存地址还并不代表一个类对象,当构造函数完成后,这个地址有足够的信息后才表示这是一个类对象。

#include 
#include 
#include 

struct Test
{
    char a;
    int b;
    int c;
    std::string str;
};

class CBase
{
public:
    CBase(): mValue(100)
    {
        printf("constructor, mValue = %d\n", mValue); 
    }
    ~CBase()
    {
        printf("destructor\n"); 
    }

    int getValue()const
    {
        return mValue;
    }
private:
    int mValue;
    Test mData;
};


int main()
{
    printf("sizeof(CBase) = %lu\n", sizeof(CBase));

    CBase *instance = new CBase();


    int value = instance->getValue();
    delete instance;

    return 0;
}

在 new 那行添加断点,如:

C++ 构造函数与this指针_第1张图片

 从这里应该可以看出,在构造函数之前,this指针已经分配了,指向的内存为0x602010,那我们可以看下这个内存里有什么,如:

C++ 构造函数与this指针_第2张图片

 此时内存里都是0,这里的x/8xw 表示打印8个单元内容,每个单元4个字节,以16进制显示,因为sizeof(CBase) = 32,所以这里打印了 32 个字节的内容。再单步往下执行,会调用 struct Test结构体的构造函数,及进行到初始化列表,如:

C++ 构造函数与this指针_第3张图片

 到这里已经进到构造函数里面了,其成员数据已经初始化完成,我们可以看到此时this指向的内存的内容发生了变化,this指向的前4个字节变成了 0x00000064,其10进制就是:100,就是初始化列表里的 mValue(100),最后两个应该是std::string 变量里的值(std::string 的内存结构这里不详述,有兴趣的同学可以去研究一下)。然后非static成员函数调用时,此时this指针指向的内容就是构造函数构造出来的内容,如:

C++ 构造函数与this指针_第4张图片

所以,我们可以得出,构造函数里的this指针指向的就是一块空内存(内容可能也是随机的),而非static成员函数里的this指针,其内存里已经有了初始化值(通过初始化列表或构造函数里赋值)。我们这里是用到了 new 操作符,那我们可以看一下 new 操作符是怎样工作的,这样也可以验证我们的结论。这里找到的文档为 microsoft 的文档:new 操作符如何工作,截取一段内容:

How new works

The new-expression (the expression containing the new operator) does three things:

  • Locates and reserves storage for the object or objects to be allocated. When this stage is complete, the correct amount of storage is allocated, but it's not yet an object.

  • Initializes the object(s). Once initialization is complete, enough information is present for the allocated storage to be an object.

  • Returns a pointer to the object(s) of a pointer type derived from new-type-id or type-id. The program uses this pointer to access the newly allocated object.

The new operator invokes the function operator new. For arrays of any type, and for objects that aren't classstruct, or union types, a global function, ::operator new, is called to allocate storage. Class-type objects can define their own operator new static member function on a per-class basis.

When the compiler encounters the new operator to allocate an object of type T, it issues a call to T::operator new( sizeof(T) ) or, if no user-defined operator new is defined, ::operator new( sizeof(T) ). It's how the new operator can allocate the correct amount of memory for the object.

文档里说明,第一步完成时,此时所分配的内存并未表示是一个 “对象”,当第2步完成后,此时的内存才表示是一个“对象”。

你可能感兴趣的:(c/c++,#,C++类/结构体,c++)