根据我目前的理解,如果你有一个类对象的向量,如果你删除了向量的任何成员,通常向量会重新分配它的一些对象以保持内存连续性。因此,您需要实现三个规则(析构函数、复制构造函数和复制赋值运算符),以便在擦除向量成员时保留所有内容。
但是:对于指向类对象的指针向量,结果对我来说不太清楚。如果我删除一个成员,那么 C++ 肯定足够聪明,可以只复制指针 - 而不是疯狂地删除指针(及其指向的类对象)然后重新创建它并再次指向它?
如果不是这样,有人可以向我解释这个白痴吗?
根据我目前的理解,如果你有一个类对象的向量,如果你删除了向量的任何成员,通常向量会重新分配它的一些对象以保持内存连续性。因此,您需要实现三个规则(析构函数、复制构造函数和复制赋值运算符),以便在擦除向量成员时保留所有内容。
但是:对于指向类对象的指针向量,结果对我来说不太清楚。如果我删除一个成员,那么 C++ 肯定足够聪明,可以只复制指针 - 而不是疯狂地删除指针(及其指向的类对象)然后重新创建它并再次指向它?
如果不是这样,有人可以向我解释这个白痴吗?
该向量将不理会您的指针值。当您推送、弹出或擦除时,它当然会移动内部数组中的值。
在这种情况下,值只是指针。但是向量中没有逻辑来确定某些东西是否是指向对象的指针并在复制值时删除/重新分配它们。
对于包含复杂类型而不是指针的向量,它当然会在重新分配或移动内部数组时尝试复制值。
向量将删除、构造和复制它包含的任何类型。在指向类/结构的指针向量的情况下,它将删除、构造和复制指针,只留下指针指向的实际对象。分配和解除分配这些由您决定。
一个例子:
如果您有以下情况:
class A
{
A() {}
}
void foo(void)
{
A * pointerToA = new A;
}
在函数 foo 作用域的末尾,唯一被释放的是变量pointerToA
本身的内存,即保存地址(32 位)的 4 个字节 - 在这种情况下,它存储在堆栈中。为 A 类的新实例分配的内存将被释放的唯一方法是手动调用 delete 并使用pointerToA
.
让我们以一个类的数组为例A
A ** arrayOfPointerToA = new A*[10];
for(unsigned i = 0; i < 10; ++i)
arrayOfPointerToA[i] = new A;
这类似于您拥有std::vector<A*>
. 你打电话时
delete [] arrayOfPointerToA;
您正在为指针数组分配内存,而不是为每个指针分配内存A
。
在上图中,由上述删除调用释放的内存以红色突出显示。请注意,A
在这种情况下,每个都存储在内存中的随机位置,因为它们都是单独分配的。
现在把它带到一个向量:
Astd::vector<A>
有效地使用 newA[size]
来分配内存。如果您要存储一个原始指针,这意味着它将分配一个 A 类型的数组,这意味着创建了size
许多类型的对象A
。当向量释放其内存size
时,类型对象的数量A
被销毁。现在举这个例子,用 A* 替换 A,你会看到 A 类型的对象没有被破坏。
这是 C++ 和指针如何工作的基本部分,而不仅仅是容器的属性。如果容器确实对每个成员任意调用 delete,这将没有意义,因为当我们拥有容器时,A
我们会在对象实例上调用 delete,而不是指向无效对象的指针。