我应该总是在函数末尾调用向量 clear() 吗?

Posted

技术标签:

【中文标题】我应该总是在函数末尾调用向量 clear() 吗?【英文标题】:Should I always call vector clear() at the end of the function? 【发布时间】:2014-03-01 08:12:55 【问题描述】:

我有一些像这样使用向量的简单函数(伪代码):

void someFunc(void) 

    std::vector<std::string> contentVector;

    // here are some operations on the vector

    // should I call the clear() here or this could be ommited ?
    contentVector.clear();


我应该调用 clear() 还是可以省略?

【问题讨论】:

析构函数将处理清理。 :) 比能好,应该省略!!这就是析构函数和 RAII 的全部意义所在。让析构函数处理清洁,你无事可做。很棒,不是吗? 这个问题展示了 C++ 的杀手级特性:RAII。在设计良好的对象中,对象的资源与对象的生命周期相关联,这在语言中得到明确支持。 【参考方案1】:

如果我们查看std::vector::~vector 的cppreference.com 条目,它会说:

破坏容器。元素的析构函数被调用,使用的存储空间被释放。请注意,如果元素是指针,则不会破坏指向的对象。

所以你不必打电话给clear。

如果我们想去draft standard,我们必须查看23.2.1部分一般容器要求4段,它说:

在表 96 和 97 中,X 表示包含 T 类型对象的容器类,a 和 b 表示 X 类型的值,[...]

然后查看Table 96 — Container requirements,它具有以下表达式条目:

(&a)->~X()  

以及以下注释:

注意:析构函数应用于 a 的每个元素;所有内存都被释放了。

更新

这是RAII 在行动中,正如Bjarne Stroustrup 在Why doesn't C++ provide a "finally" construct? 中所说:

因为 C++ 支持几乎总是更好的替代方案:“资源获取即初始化”技术(TC++PL3 第 14.4 节)。基本思想是用一个本地对象来表示一个资源,这样本地对象的析构函数就会释放资源。这样,程序员就不会忘记释放资源。

【讨论】:

【参考方案2】:

完全没有必要这样做。 std::vector 和所有其他容器会在它们自己被销毁时自动销毁它们的元素。这意味着它们的析构函数负责该操作。所以,不要。

这样的美妙之处在于容器自然是异常安全的[1]

void someFunc(void) 

    std::vector<std::string> contentVector;

    // here are some operations on the vector

    throw std::runtime_error("I just want to throw!");

    contentVector.clear();

会调用contentVector.clear(); 行吗?不,但你仍然是安全的,因为保证会调用 contentVector 的析构函数。

来自vector[2]

破坏容器。元素的析构函数被调用,使用的存储空间被释放。请注意,如果元素是指针,则不会破坏指向的对象。


[1]你仍然需要让你的元素异常安全(让它们在调用析构函数时正确释放资源)。

[2]有关 SGI STL 文档的一些想法,请参阅下面的 cmets

【讨论】:

SGI 不是权威参考。只是说'因为我确信在这种情况下它是正确的。 @MarkRansom 一个链接 cppreference,另一个 cplusplus.com,然后我...;)。 SGI STL 网站肯定是一个很好的资源,如果不是权威的话。 OP 肯定会从这个“经典”网站中学到一些东西。 问题是SGI没有记录官方标准,它记录了它的前身。有一些微妙和不那么微妙的差异。见***.com/questions/5266386/… @MarkRansom 我知道。但是很高兴知道它在这种情况下具有相同的行为,即使它是标准库的前身,这意味着您仍然可以依赖旧编译器的行为/保证。【参考方案3】:

不需要,一旦超出范围即自动清除,即destructor will destroy the container object.

【讨论】:

您能否提供一些指向描述此行为的 STL 文档的链接并将其粘贴到您的回答中? 社区共识is that cplusplus.com is not a good reference.【参考方案4】:

您可以省略使用 .clear() 函数,因为一旦 contentVector 在“”处超出范围,vector's destructor 就会运行。

这会释放存储向量数据的内存。

【讨论】:

社区共识is that cplusplus.com is not a good reference.【参考方案5】:

因为我认为没有其他人提到过这一点,但如果你的向量是

std::vector<std::string*> vector;

您应该在函数完成之前释放分配给每个元素的内存(除非您已将所有权传递给其他地方 - 例如全局变量等)

for (auto i : vector) 
  delete i;

【讨论】:

如今,随着 C++11 变得相当普遍,您可能应该使用 std::unique_ptr&lt;std::string&gt; 而不是 std::string*,以便机器也能处理好这个问题。而且由于您的 foreach 循环表明正在使用 C++11,这就是我要走的路。顺便说一句,这是Mark's answer 中的脚注 1 所涉及的一个方面。 我写了 auto 部分,因为我懒得写出没有 vim 宏的完整版本。如果你有 c++11 或 boost,那么是的。但是指针析构函数不会释放内存(显然无法更改)

以上是关于我应该总是在函数末尾调用向量 clear() 吗?的主要内容,如果未能解决你的问题,请参考以下文章

编码标准:是不是应该总是在每个方法或函数的末尾写“return”? [复制]

C++ 堆栈分配对象,显式析构函数调用

当我完成向量时,是否需要调用clear()? [重复]

C ++擦除向量末尾的一部分而不重新分配

为啥我不能从 onclick 属性调用名为 clear 的函数?

JavaScript 的 array.clear() 不是函数吗? [复制]