【发布时间】:2012-12-14 17:46:09
【问题描述】:
我研究了STL向量的实现。 矢量容器被实现为动态数组。 clear() 方法用于销毁向量中的所有元素,它将向量的大小设置为 0,但容量保持不变。所以,如果我理解正确,所有元素都被称为它们的析构函数,但动态分配的内存仍然可用。为了仍然释放它,我们可以这样做:
Vec.swap( vector<T>() ); // Capacity = 0.
但是让我们假设我们没有使用交换,只是明确了。 内部实现(如果我错了,请纠正我)大约等于以下内容(以非常简化的方式):
// 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() 的部分功能,以及我从研究中得出的结论,如果我错了,您可以纠正我。
【问题讨论】:
-
这是关于
vector的一些假设实现还是关于对象破坏的机制? -
@honk - 实际上,由于 clear 调用破坏,它们都是相关的
-
如果我可以给您一点建议,请阅读 Scott Meyer 的书籍:有效的 STL 和更有效的 C++。前者解释了你的疑问,公平的。
标签: c++ oop stl destructor undefined-behavior