std::vector<T>::clear()会调用内容的析构函数吗?

24

如果我有一个std::vector存储一些东西(比如说数据),那么std::vector::clear()方法会调用容器内元素的析构函数吗?例如,如果我的数据是用vector存储的,以下代码是否有效?

char * pd;
for(vector<char *>::iterator it = data.begin(); it != data.end(); ++it) {
  pd = *it;
  delete pd;
}

那么,它是否多余了?因为data.clear()会做到这一点。我认为不是,也就是说需要手动释放内容。我猜想,data.clear()不会调用内容的隐式析构函数,这正确吗?这是针对C++11之前的版本。


1
char * 没有析构函数,但是当类型具有时, vector::clear 会调用其析构函数。 - Raxvan
除非您在向量中存储smart_ptr(unique_ptr),否则需要手动释放内存。 - Eric Fortin
严格来说,您的循环具有未定义的行为。(实际上,如果您将立即调用clear或销毁向量,则不必担心。但是,否则我不会在向量中留下已删除对象的指针。) - James Kanze
3个回答

29
回答您的标题:std::vector<T>::clear() 会调用每个元素的析构函数。然而,对于像 char* 这样的原始数据类型,析构函数是微不足道的(标准术语为“什么也不做”),这几乎等同于不调用析构函数。
注意:析构函数与 delete 操作符不同。
因此,你应该问的问题是:“std::vector<T*>::clear() 是否在其元素上调用 delete?” 答案是否定的。你必须手动执行它,就像你的示例代码所示,或者你可以(并且可能应该)使用像 std::string 或智能指针等对象代替原始指针。它们会为你管理内存,它们的析构函数(见上文)会自动调用 delete

10
std::vector<T>::clear() 函数总是会调用每个元素的析构函数,但指针类型的析构函数通常是空操作(或者是 trival 析构函数)。这与你在实践中所说的差不多,但更接近标准所描述的内容。 - James Kanze
@JamesKanze 感谢你的纠正,我已经相应地编辑了答案。 - Arne Mertz
1
非正式地说,你可以说销毁向量也会销毁所有指针,但只是指针,而不是它们所指向的对象 ;) - Micka
据我所知,作为一种优化,POD类型不会调用它们的析构函数。 - Adrian
1
@Adrian 这在概念上与 POD 析构函数是无操作相同。 - Arne Mertz

9
如果您的项是动态分配的,并且您的向量包含对它们的指针,则在调用clear()之前必须手动对该容器中的每个指针调用delete,否则会出现内存泄漏。
如果它们是未动态分配的对象,则不需要进行任何操作-在清除向量时,向量中的对象的析构函数(如果有)将被调用。

5

3
它确实会调用指针的析构函数。只是指针的析构函数是一个不执行任何操作的平凡析构函数。它不会特殊调用delete(毕竟,您可以拥有一个std::vector<char*>,其中char*是在堆栈上分配的)。 - Sylvain Defresne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接