我研究过STL vector的实现。 vector 容器被实现为一个动态数组。方法 clear() 用于破坏 vector 中的所有元素,它将 vector 的大小设置为 0,但容量保持不变。所以,如果我理解正确的话,所有的元素都被称为它们的析构函数,但是动态分配的内存仍然可用。为了仍然释放它,我们可以这样做:
Vec.swap( vector<T>() ); // Capacity = 0.
但是假设我们没有使用swap,只是做了一个clear。 内部实现(如果我错了请纠正我)大约等于以下内容(以非常简化的方式):
// A contained type:
struct C {
int m;
C() : m(123){}
};
C * arr = new C[10]; // Suppose this is the internal array in the container
编辑: 我知道上面的new运算符并没有在实际实现中使用,STL使用分配器,我只是用new作为测试用例来测试析构函数(这只是一个类比)。
// Calling clear() :
for(size_t i=0;i<SZ;i++)
arr[i].~C(); // Destroying ALL elements
// some other actions . . .
但是现在容量还是10,内存还有一些我们可以访问的数据:
// Accessing the vector at 0:
cout<<arr[0].m<<endl; // This prints 123
这是未定义的行为吗?嗯,看起来是这样,但我想确定一下。
也许如果我更深入地了解调用析构函数时会发生什么(关于堆栈内存),我可以肯定地知道,这是否等于当程序超出函数范围时调用析构函数,或者在退出范围之前调用析构函数被认为与任何方法一样,并且对象的堆栈内存未被释放?
免责声明:上面的代码非常简化,以象征 clear() 所做的部分工作,以及我从研究中得出的结论,如果我错了,您可以纠正我。
最佳答案
std::vector<...>::clear()
是正确的只是销毁对象并适本地设置其内部记录以指示没有对象。当访问被销毁的对象时,您有未定义的行为:虽然数据中的位可能没有改变,但关联的对象也可能已被销毁,并且它们的内存被回收用于其他目的。
在你的例子中 C
只存储一个 int
并且在析构函数中不对它做任何事情,这些位可能没有改变但不能保证那样。特别是调试实现可能会浪费几个周期来故意将垃圾写入被销毁对象的内存中。
只是一个旁注:std::vector<...>
不会使用 new C[n]
而是通过分配器分配和释放原始内存。然而,这是一个细节。
关于c++ - vector::clear() 幕后和破坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14086816/