我的基本程序结构如下:
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
换句话说,每个对象的向量占用内存中的相同空间。程序输出也是如此,因为通过不同的对象访问向量中的数据会给出相同的值,即使它们应该是不同的。当然,另一个奇怪的事情是它为我提供了与对象相同的地址。
答案 0 :(得分:3)
忽略程序中的大量错误......
A.push_back(A());
这会创建一个A
类型的临时对象。 object_B2.pB1
成员变量初始化为指向此临时对象的object_B1
成员变量。
然后将此临时A
对象复制到someA
容器中。此副本的object_B1
成员变量的地址不同,但您不更新object_B2.pB1
成员变量以指向新实例。为此,您需要实现一个复制构造函数(为了正确起见,您还需要实现一个复制赋值运算符)。
所有指针最终都是相同的原因是临时对象都是在内存中的相同位置创建的,这使得因为你可能在循环中调用push_back
,所以临时对象可以在循环的每次迭代中在同一位置的堆栈上创建。
答案 1 :(得分:2)
您缺少A的副本ctor,默认的副本语义将指针值从一个B2对象复制到另一个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 =声明为私有而不定义它。