2

私はこの質問をしました。私の質問は、これがどのように機能するかです。詳しく説明すると、まだ初期化されていないオブジェクトをどのように指すことができますか。この MWE を作成したところ、オブジェクトがコピー作成されたものであり、コピーが割り当てられたものではないことがわかります。つまり、オブジェクトはまだ初期化されていませんが、それを指すことができます。

#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

メモリがどのように処理されるかを詳しく説明することを恐れないでください。そして、すべてのメンバーが住んでいる場所。

4

2 に答える 2

5

初期化を割り当てと間違えないでください。BarChild :: fooは、コンストラクターが所定の位置に格納されているため、コンストラクターが呼び出される前に割り当てられます。したがって、BarParent::p_fooが指す場所が明確に定義されています。FooのコンストラクターはBarChild::fooを初期化しますが、コンストラクターが呼び出される前にBarChild :: fooから読み取ろうとしない限り、順序に気付くことはありません。

于 2013-03-19T23:07:34.067 に答える
3

この行で

BarChild bar(foo);

コンパイラーはオブジェクト用に十分なスタックスペースを予約しBarChild、コンストラクターを呼び出してオブジェクトの存続期間を開始します。オブジェクト内では、fooメンバーは固定オフセットをBarChild持ち、すべてのオブジェクトはそのfoo中の同じオフセットにメンバーを持っています。したがって、thisポインターはコンストラクター内の既知のアドレス(barスタック上ののアドレス)を持っているため、既知のアドレスthis->fooにもあります。そのアドレスのメモリがまだ初期化されていなくても。BarChildオブジェクトは、各メンバーが初期化されるときに「大きくなる」ことはなく、そのサイズは固定されており、すべてのメンバーのスペースは、初期化される前にすでに「予約」されています。

これは、次のようなものです。

 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

オブジェクトはまだ存在しておらず、使用することはできませんが、初期化される前にそのアドレスがわかっています。

于 2013-03-19T23:07:25.897 に答える