【问题标题】:How should I delete objects in a vector我应该如何删除向量中的对象
【发布时间】:2015-07-15 02:59:02
【问题描述】:

我正在制作一个使用 std::vector 来保存一堆对象的程序。

std::vector<Ball> balls;
for (int i = 0; i < ball.size(); ++i){
  if (...some condition...){
    //How should I delete balls[i]
  }

如果我这样做了

std::vector<Ball> balls;
//put a bunch of balls in balls
for (int i = 0; i < ball.size(); ++i){
  if (...some condition...){
    balls.erase(balls.begin() + i);
  }

每个球中没有动态分配的内存,那么这是否完全清理了balls[i]?我永远不必担心公羊上的那个球吗?

感谢大家的帮助!

【问题讨论】:

  • 是的,球会自动销毁。
  • 这个循环有问题。当你擦除元素i 时,它后面的所有元素都会向下移动。然后,当您增加 i 时,您将跳过刚刚移动到其位置的球。
  • 删除项目时请确保跳过++i。否则,您将跳过处理向量的某些项。
  • @RSahu 老实说,OP 应该使用 erase 返回的迭代器,或者使用 remove_if-erase 习惯用法。手动处理索引只会导致不必要的非一错误
  • @KABoissonneault,VladFromMoscow 的回答提出了从向量中删除项目的正确方法。如果 OP 坚持他的策略,那么了解这个陷阱对他们来说很重要。

标签: c++ visual-c++ vector


【解决方案1】:

“每个球中没有动态分配的内存,所以这是否完全清理了balls[i]?我永远不必担心内存中存在那个球吗?”

是的,您不必担心Ball 类实例,但内存管理由std::vector&lt;&gt; 类在内部完成。所以这并不意味着std::vector&lt;&gt; 会自动收缩它为删除的项目动态分配的内存。

使用当前标准,您可以在删除多个项目后使用std::vector&lt;&gt;::shrink_to_fit() 建议实施。

【讨论】:

  • 收缩以适应不会“强制”或保证任何事情。正如您链接到的页面所说,这是一个不具约束力的请求。
【解决方案2】:

您可能需要应用 erase_remove 成语进行条件清理:

balls.erase(std::remove_if(balls.begin(), balls.end(),
               [] (const Ball& el) { //write your condition here;})balls.end());

【讨论】:

    【解决方案3】:

    我认为你的意思是以下

    #include <vector>
    #include <algorithm>
    
    //...
    
    std::vector<Ball> balls;
    //...
    
    balls.erase( std::remove_if( balls.begin(), balls.end(), 
                                 [] ( const Ball &b ) { return somecondition( b ); } ),
                 balls.end() );       
    

    方法 erase 将为向量的所有已擦除元素调用析构函数。事实上,该类调用了一个布局释放函数。

    【讨论】:

    • 我想你是想回答这个问题。这可能是一段更惯用的代码,但它不是上述问题的答案。
    【解决方案4】:

    首先,当您在向量上调用erase() 时,该类型的析构函数被调用的次数等于被擦除的元素数(C++11 23.3.7.5.5)。擦除元素之后的所有元素都向前移动以占用空白空间。我们不会通过此操作恢复内存,因为我们不会更改容器的容量。

    其次,您可以使用标准算法std::remove_if() 和lambda 来摆脱满足特定条件的元素。这是一个如何工作的小例子:

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    
    int main()
    {
        std::vector<int> foo = {1,2,3,4,5,5,5,5,6,7,8,9};
        std::remove_if(foo.begin(), foo.end(), [](int i){ if(i == 5) return true; else return false; });
        for (const auto & e : foo)
            std::cout << e << " ";
    }
    

    Live Example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-28
      • 1970-01-01
      • 1970-01-01
      • 2013-07-05
      • 2014-05-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多