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

Posted

技术标签:

【中文标题】给定该类的对象数组,为类成员向量分配内存有问题吗?【英文标题】:trouble with memory allocation for a class member vector, given an array of objects of that class? 【发布时间】:2011-02-20 04:58:40 【问题描述】:

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

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】:

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

A.push_back(A());

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

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

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

【讨论】:

@Nawaz:是的,应该,而且会,这正是 OP 所要求的行为。 默认的复制构造函数也应该复制地址。 @Nawaz:这正是问题所在,请参阅我的答案中的明确测试用例。 @Fred 和@James :我想我误读了这个问题,可能是因为它不够清楚。【参考方案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= 声明为私有而不定义它。

【讨论】:

我不明白复制构造函数的参数应该是什么。为什么我必须将 object_B1 更改为 x?我不能只更改 object_B2.pB1 中的值吗? @MattMunson:复制ctor的参数是复制的来源;在 "A a2 = a1;" 中,x 是对 a1 的引用。 如果我省略了这一行,': object_B1 (x.object_B1)' 是否意味着 object_B1 仍将具有与其复制的对象中相同的地址? @MattMunson:那是一个“构造函数初始化器”;查一下。它与 this->object_B1 或 x.object_B1 的地址无关;它所做的是将一个对象的 复制到另一个对象,在这种情况下复制 B1 的向量数据成员。 @MattMunson:或多或少,是的。一个类在 C++ 中几乎总是有一个复制 ctor(如果您不声明,编译器会生成一个),“复制 ctor”意味着一组非常具体的签名。查找“三法则”可能会有所帮助。

以上是关于给定该类的对象数组,为类成员向量分配内存有问题吗?的主要内容,如果未能解决你的问题,请参考以下文章

Java 面向对象(十四)

何时使用 alloca 为类成员分配内存?

java反射

java之反射

我们可以控制向量数组(c++)中元素的内存分配吗?

00108_类加载器