指向尚未初始化的成员

时间:2013-03-19 22:46:49

标签: c++ pointers inheritance member

我问了this问题。我现在的问题是 这有效吗?详细说明,我如何指向尚未初始化的对象。我已经制作了这个MWE并且它显示该对象是创建的副本而不是复制分配的.i.e。该对象尚未初始化但我能够指出它。

#include <iostream>

class Foo {
public:
    int x;

    Foo(const Foo& ori_foo) {
        std::cout << "constructor" << std::endl;
        x = ori_foo.x;
    }

    Foo& operator = (const Foo& ori_foo) {
        std::cout << "operator =" << std::endl;
        x = ori_foo.x;
        return *this;
    }

    Foo(int new_x) {
        x = new_x;
    }
};

class BarParent {
public:
    Foo *p_foo;

    BarParent(Foo* new_p_foo) : p_foo(new_p_foo)
    {
       std::cout << (*new_p_foo).x << std::endl;
    }
};

class BarChild : public BarParent {
public:
    Foo foo;

    BarChild(Foo new_foo)
        :BarParent(&foo) //pointer to member not yet initialised
        ,foo(new_foo) // order of initilization POINT OF INTEREST
        {}
};

int main()  {
    Foo foo(101);

    BarChild bar(foo);

    std::cout << bar.p_foo->x << std::endl;
std::cout << bar.foo.x << std::endl;
}

输出:

constructor
0
constructor
101
101

不要害怕详细了解内存的处理方式。而且,每个成员都居住在哪里。

2 个答案:

答案 0 :(得分:5)

不要将初始化误认为是分配。 BarChild :: foo将在构造函数被调用之前被分配,因为它存储在原位,因此BarParent :: p_foo将有一个定义良好的位置指向。 Foo的构造函数将初始化BarChild :: foo,但只要你在调用构造函数之前没有尝试从BarChild :: foo读取,你就不会注意到它的顺序。

答案 1 :(得分:3)

在这一行

BarChild bar(foo);

编译器为BarChild对象保留足够的堆栈空间,然后调用构造函数来开始对象的生命周期。在foo成员具有固定偏移量的对象内,每个BarChild对象在其中具有相同偏移量的foo成员,因此this指针具有已知地址在构造函数内(它是堆栈上bar的地址),this->foo也在一个已知地址,即使该地址的内存尚未初始化。 BarChild obejct在每个成员初始化时不会“变大”,其大小是固定的,并且所有成员的空间在初始化之前已经“保留”。

这有点类似于:

 char raw_memory[sizeof(Foo)];  // define block of uninitialized memory
 char* addr = raw_memory;       // take address of uninitialized memory
 new (raw_memory) Foo;          // initialize memory

该对象尚不存在,使用它无效,但其地址在初始化之前就已知道。