C++ - 对于指向对象的指针向量,重新分配是否会导致对象的删除和复制?

C++ - For a vector of pointers to an object, does reallocation cause deletion and copying of objects?

提问人:metamorphosis 提问时间:3/28/2014 更新时间:3/28/2014 访问量:975

问:

根据我目前的理解,如果你有一个类对象的向量,如果你擦除向量的任何成员,通常该向量会重新分配它的一些对象,以保持内存的连续性。因此,您需要实现三规则(析构函数、复制构造函数和复制赋值运算符),以便在擦除向量成员时保留所有内容。

但是:对于指向类对象的指针向量,结果对我来说不太清楚。 如果我擦除一个成员,那么 C++ 肯定足够聪明,可以复制指针 - 而不是疯狂地删除指针(以及它指向的类对象),然后重新创建它和它再次指向的对象?

如果不是这样,有人可以向我解释这种愚蠢吗?

C++ 指针 三分法

评论


答:

2赞 Peter Clark 3/28/2014 #1

向量将删除、构造和复制它包含的任何类型。对于指向类/结构的指针向量,它将删除、构造和复制指针,而不保留指针指向的实际对象。由您来分配和取消分配这些内容。


编辑

举个例子:

如果您有以下情况:

class A
{
  A() {}
}

void foo(void)
{
   A * pointerToA = new A;
}

在函数 foo 作用域的末尾,唯一被释放的是变量本身的内存,即保存地址(32 位)的 4 个字节——在这种情况下,该地址存储在堆栈上。释放为类 A 的新实例分配的内存的唯一方法是手动调用 delete,地址为 。pointerToApointerToA

让我们以类数组为例A

A ** arrayOfPointerToA = new A*[10];
for(unsigned i = 0; i < 10; ++i)
  arrayOfPointerToA[i] = new A;

这类似于当你有 .当您致电时std::vector<A*>

delete [] arrayOfPointerToA;

您正在为指针数组解除分配内存,而不是为每个 .A

enter image description here

在上图中,上述删除调用释放的内存以红色突出显示。请注意,在这种情况下,每个都存储在内存中的随机位置,因为它们都是单独分配的。A

现在把它带到一个向量上:

A 有效地使用 new 来分配内存。如果要存储原始指针,这意味着它将分配一个类型为 A 的数组,这意味着将创建多个类型的对象。当向量释放其内存时,会销毁许多类型的对象。现在以该示例为例,将 A 替换为 A*,您将看到没有 A 类型的对象被销毁。std::vector<A>A[size]sizeAsizeA

这是 C++ 和指针工作的基本部分,而不仅仅是容器的属性。如果容器确实对每个成员任意调用 delete,这将没有意义,因为当我们有一个容器时,我们会对对象的实例调用 delete,而不是指向无效对象的指针。A

评论

1赞 metamorphosis 3/28/2014
我宁愿希望是这样,但是在网络上看到了相互矛盾的陈述,表明当指针被删除时,与之关联的类对象也会被删除 - 就像在指针上调用“delete”将调用它指向的对象的析构函数一样。C++ 上是否有任何与此问题相关的文档?
0赞 Peter Clark 3/28/2014
它本身的指针被删除,也就是说,保存指针值的 4 个字节(在 32 位计算机/操作系统上)被释放。指针是独立于它所指向的内存的实体,这是在分配(新)对象时分配的实体。这个类似问题的答案比我更深入地解释了它。我会用更多的信息来编辑我的帖子。
1赞 Connor Hollis 3/28/2014 #2

该向量将不理会您的指针值。当然,当您推送、弹出或擦除时,它会移动内部数组中的值。

在本例中,值只是指针。但是,向量中没有逻辑来确定某物是否是指向对象的指针,并在复制值时删除/重新分配它们。

对于包含复杂类型而不是指针的向量,它当然会在重新分配或移动内部数组时尝试复制值。

评论

2赞 metamorphosis 3/28/2014
谢谢康纳——你的两个答案实际上都一样好,我只是或多或少地抛硬币选择了一个;)
1赞 Connor Hollis 3/28/2014
@metamorphosis完全没问题。实际上,我们在学校里坐在一起:P