我应该总是在函数末尾调用向量 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<std::string>
而不是 std::string*
,以便机器也能处理好这个问题。而且由于您的 foreach 循环表明正在使用 C++11,这就是我要走的路。顺便说一句,这是Mark's answer 中的脚注 1 所涉及的一个方面。
我写了 auto 部分,因为我懒得写出没有 vim 宏的完整版本。如果你有 c++11 或 boost,那么是的。但是指针析构函数不会释放内存(显然无法更改)以上是关于我应该总是在函数末尾调用向量 clear() 吗?的主要内容,如果未能解决你的问题,请参考以下文章
编码标准:是不是应该总是在每个方法或函数的末尾写“return”? [复制]