1

私の基本的なプログラム構造は次のとおりです。

class B1 
{
    vector <someStruct> aStruct; //some struct contains a vector of 'someotherStruct's, etc
    B1() { cout << &aStruct << " ";};
};


class B2 {B1* pB1;};

class A
{
    B1 object_B1;
    B2 object_B2;

    A() { objectB2.pB1 = &object_B1;}; 
};

int main()
{
    vector <A> someA;
    for(int q=0; q < N; q++)
        someA.push_back(A()); 

    cout << endl;

    for (int q=0; q < N; q++)
        cout << someA[q].B2.pB1 << " ";
}

したがって、Nが5の場合、出力は次のようになります。0xbffff828 0xbffff828 0xbffff828 0xbffff828 0xbffff828 \ n
0xbffff828 0xbffff828 0xbffff828 0xbffff828 0xbffff828

つまり、各オブジェクトのベクトルはメモリ内の同じスペースを占有します。また、プログラム出力もこれを裏付けています。異なるオブジェクトを介してベクター内のデータにアクセスすると、異なるはずの場合でも同じ値が得られるためです。もちろん、もう1つの奇妙なことは、ベクトルのアドレスがオブジェクトのアドレスと同じになることです。

4

2 に答える 2

3

プログラム内の多数のエラーを無視します...

A.push_back(A());

これにより、タイプがの一時オブジェクトが作成されますA。メンバー変数は、この一時オブジェクトのメンバー変数をobject_B2.pB1指すように初期化されます。object_B1

次に、この一時Aオブジェクトがコンテナにコピーされます。someAこのコピーのメンバー変数のアドレスは異なりますが、新しいインスタンスを指すようにメンバー変数をobject_B1更新しません。object_B2.pB1これを行うには、コピーコンストラクターを実装する必要があります(正確を期すために、コピー代入演算子も実装する必要があります)。

すべてのポインタが同じになる理由は、一時オブジェクトがすべてメモリ内の同じ場所に作成されるためです。これは、おそらくpush_backループで呼び出しているため、一時オブジェクトをスタック上に作成できるためです。ループの各反復で同じ場所にあります。

于 2011-02-20T05:09:31.900 に答える
2

Aのコピーコンストラクターがありません。デフォルトのコピーセマンティクスは、ポインター値を1つのB2オブジェクトから別のオブジェクトにコピーします。構造体の各アイテムは、すべて同じソースオブジェクトからコピーされるため、同じアドレスを参照します。このポイントされたオブジェクトが後で破棄されると、UBがそれにアクセスできるようになります。

A a1;
A a2 = a1;
assert(a2.object_B2.pB1 == &a1.object_B1);  // Danger Will Robinson!

修正:

struct A {
  B1 object_B1;
  B2 object_B2;

  A() { objectB2.pB1 = &object_B1; }
  A(A const &x)
  : object_B1 (x.object_B1)
  {
    object_B2.pB1 = &object_B1;
  }
};

デフォルトの演算子にも同様の問題があるため、コピー代入演算子も必要です。無効にする場合は、このop=を定義せずにプライベートとして宣言します。

于 2011-02-20T05:10:11.707 に答える