【问题标题】:Will this Free the data correctly?这会正确释放数据吗?
【发布时间】:2013-01-04 03:17:54
【问题描述】:

我只想知道这是否会正确释放数据。

伪代码:

std::map<std::string, ClassPointer*>::iterator tempIterator;

    for(tempIterator = directory.begin(); tempIterator < directory.end; 
        tempIterator++)
        delete &tempIterator;

【问题讨论】:

  • 我认为您不需要 & 因为迭代器已经是指向地址位置的指针。如果我错了,请纠正我。
  • 这可以通过使用 valgrind 来验证。如果您在 memcheck 应用程序中运行您的 C++ 代码,它应该能够告诉您是否所有内存都已正确释放。
  • @Ben 和 OP 应该是 delete *tempIterator
  • @SethCarnegie 容器是地图,应该是 delete tempIterator-&gt;second ?
  • @SethCarnegie 我试过了,结果出错了。 &tempIterator 从来没有给我一个错误。无论如何,我认为我通过删除 tempIterator->second 解决了答案。

标签: c++ memory iterator memory-leaks allocation


【解决方案1】:

如果ClassPointer*new[] 一起分配,则这段代码可能无法正常工作。使用智能指针是一个更好的主意。

仅供参考,应该是

for (auto tempIterator = directory.begin(); tempIterator != directory.end(); 
    ++tempIterator)

【讨论】:

  • 我真的怀疑ClassPointer* 是由new[] 分配的,因为这样(在映射中只存储一个指针)他失去了一个数组大小,所以原始指针变得无用...没有办法遍历该数组...
  • @zaufi 在某些情况下,对象由new[] 分配并插入map,但这不是最佳做法。
【解决方案2】:

由于目录存储原始指针,因此您有责任在必要时删除这些指针。

std::map<std::string, ClassPointer*>::iterator tempIterator;

for(tempIterator = directory.begin(); tempIterator < directory.end(); 
    tempIterator++)
{
    delete tempIterator->second;
}

总是,更好的解决方案是在 STL 容器中使用智能指针:

 std::map<std::string, std::shared_ptr<ClassPointer>> directory;

【讨论】:

    【解决方案3】:

    正确的做法是:

    for (
        std::map<std::string, ClassPointer*>::iterator it = directory.begin()
      , last = directory.end()     // avoid call to end() every time
      ; it != last                 // use operator != (NOT operator <)
      ; ++it                       // prefer prefix increment for iterators!
      ) delete it->second;         // iterator points to std::pair actually!
    

    或C++11方式:

    for (auto& item : directory) delete item.second;
    

    顺便说一句,这只会释放一个类指针,而不是一个映射元素! (因此地图中的指针无效,但项目仍在地图中)

    【讨论】:

    • 关于不要每次都调用 end() 的建议已经过时了。所有标准库都兑现了这个价值。如果它不改变获得它的成本是恒定的(并通过内联优化)。这是一个过早的优化,让编译器在你处理算法的这种优化上工作。
    • @LokiAstari 你能给我一个关于“所有标准库兑现这个价值”的 100% 保证吗? 'ALL' 是否包括所有编译器/库的所有过去和未来版本? :) (只是简单地看一下 gcc 4.7.2 的 STL 告诉我你错了)标准没有这样的保证!所以这就是为什么更好明确地显示这一点(将其视为一种编码风格!)。当然,现代 C++ 编译器会(可能)将该调用移出 for 主体,但显式使用 last 只会帮助他们避免做这项工作......所以我认为这个功能主要是一种好的做法(编码风格)不是一种优化...
    • @zuufi:他们做或不做有关系吗?不,这里的优化使代码更难阅读。更难维护(因为身体的变化可能会出错)。很难写。这也是这里对编译器的许多简单优化。所以没有使用它的兑换功能。
    • @LokiAstari ...我认为这是一种很好的做法,因为调用end() 只是一个最简单的情况。这里有很多情况,尤其是当您使用迭代器适配器(如 std::make_move_iterator,或来自 boost::iterator 库的 smth,如 transform_iterator)时,总是最好在其中显式引入 last 变量for... 的范围使代码可读和可维护
    • 我没有错(请仔细阅读我的声明)。不;这不好的做法。大约十年前,人们试图鼓励这种做法。它从未在主流中流行,我认为它是非惯用的 C++,因此更难读/写和维护。看看你在其他多少地方看到了这个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    • 2011-05-07
    • 2016-06-24
    相关资源
    最近更新 更多