给定该类的对象数组,类成员向量的内存分配有问题吗?

发布于 2024-10-18 09:03:00 字数 798 浏览 6 评论 0原文

我的基本程序结构是这样的:

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

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

My basic program structure is this:

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 << " ";
}

So if N was 5, the output would be:
0xbffff828 0xbffff828 0xbffff828 0xbffff828 0xbffff828 \n
0xbffff828 0xbffff828 0xbffff828 0xbffff828 0xbffff828

In other words, each object's vector occupies the same space in memory. And program output bears this out as well, since accessing data in the vector through different objects gives the same values, even when they should be different. The other weird thing, of course, is it gives me the same address for the vector as for the object.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南城旧梦 2024-10-25 09:03:00

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

A.push_back(A());

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

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

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

Ignoring the large number of errors in the program...

A.push_back(A());

This creates a temporary object of type A. The object_B2.pB1 member variable is initialized to point to the object_B1 member variable of this temporary object.

This temporary A object is then copied into the someA container. The address of this copy's object_B1 member variable is different, but you don't update the object_B2.pB1 member variable to point into the new instance. To do this, you would need to implement a copy constructor (and, for correctness, you would also need to implement a copy assignment operator).

The reason that all of the pointers end up being the same is that the temporary objects are all created in the same location in memory, which makes since, since you are presumably calling push_back in a loop, so the temporary object can be created on the stack in the same place at each iteration through the loop.

总以为 2024-10-25 09:03:00

您缺少 A 的复制因子,并且默认复制语义将指针值从一个 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=,请将其声明为私有而不定义它。

You are missing a copy ctor for A and the default copy semantics copy the pointer value from one B2 object to another. Each item in the struct sees the same address because they are all copied from the same source object. When this pointed-to object is later destroyed, you'll have UB accessing it.

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

The fix:

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;
  }
};

You also need a copy-assignment operator because the default one has a similar problem. Declare this op= as private without defining it if you want it disabled.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文