【问题标题】:Should I always call vector clear() at the end of the function?我应该总是在函数末尾调用向量 clear() 吗?
【发布时间】: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。在设计良好的对象中,对象的资源与对象的生命周期相关联,这在语言中得到明确支持。

标签: c++ vector stl stdvector


【解决方案1】:

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

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

所以你不必打电话给clear

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

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

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

(&a)->~X()  

以及以下注释:

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

更新

这是RAII 在行动中,正如Bjarne StroustrupWhy 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没有记录官方标准,它记录了它的前身。有一些微妙和不那么微妙的差异。见stackoverflow.com/questions/5266386/…
    • @MarkRansom 我知道。但是很高兴知道它在这种情况下具有相同的行为,即使它是标准库的前身,这意味着您仍然可以依赖旧编译器的行为/保证。
    【解决方案3】:

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

    【讨论】:

    【解决方案4】:

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

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

    【讨论】:

    【解决方案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,那么是的。但是指针析构函数不会释放内存(显然无法更改)
    猜你喜欢
    • 2010-11-05
    • 2018-04-23
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    • 2012-03-20
    • 2014-07-03
    • 1970-01-01
    • 2019-08-22
    相关资源
    最近更新 更多