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

换句话说,每个对象的向量在内存中占据相同的空间。程序输出也证明了这一点,因为通过不同对象访问向量中的数据会给出相同的值,即使它们应该不同。当然,另一个奇怪的事情是它为我提供了与对象相同的向量地址。

4

2 回答 2

3

忽略程序中的大量错误...

A.push_back(A());

这将创建一个类型为 的临时对象Aobject_B2.pB1成员变量被初始化为指向这个临时对象的object_B1成员变量。

然后将此临时A对象复制someA容器中。这个副本的object_B1成员变量的地址不同,但是你没有更新object_B2.pB1成员变量指向新的实例。为此,您需要实现一个复制构造函数(并且,为了正确起见,您还需要实现一个复制赋值运算符)。

所有指针最终都相同的原因是临时对象都是在内存中的同一位置创建的,这使得因为您可能是push_back在循环中调用,所以临时对象可以在堆栈上创建在循环的每次迭代中都在同一个地方。

于 2011-02-20T05:09:31.900 回答
2

您缺少 A 的复制 ctor,并且默认复制语义将指针值从一个 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 回答