【问题标题】:Is it possible to erase elements of a std::list in a c++11 for each loop是否可以在 c++11 中为每个循环擦除 std::list 的元素
【发布时间】:2013-01-13 15:32:53
【问题描述】:

我想为每个循环使用新的 C++11 来迭代列表的所有元素并删除某些元素。例如

std::list<int> myList;
myList.push_back(1); 
myList.push_back(13);
myList.push_back(9);
myList.push_back(4);

for(int element : myList) {
    if(element > 5) {
        //Do something with the element

        //erase the element
    }else{
        //Do something else with the element
    }
}

是否可以使用 for each 循环来执行此操作,或者我是否必须返回迭代器才能实现此操作?

【问题讨论】:

  • 为什么不能使用 remove_if/erase?
  • 或者只是list::remove_if,不需要迭代器。
  • @KarthikT 和@BenjaminLindley:对不起,我没有在我的问题中提及。我想对满足条件的元素以及所有其他元素做一些事情。我可能可以将它放入list::remove_if 使用的谓词函数中,但我发现这不是很好。
  • @Haatschii 取决于处理的性质,如果它对性能不太重要,我会分两遍完成,这样更干净。

标签: c++ stl c++11


【解决方案1】:

你应该能够做到这一点

myList.erase(std::remove_if(myList.begin(), myList.end(),
    [](int& element) 
    { 
        return element > 5;
    } 
    ),myList.end());

或者简单地说(由本杰明·林德利提供)

myList.remove_if(
    [](int& element) 
    { 
        return element > 5;
    } 
    );

【讨论】:

  • 移动元素对于列表来说效率很低
  • 嗯,不错的编辑 :) 但是等等...std::erase?你试过编译这个吗?
  • @Cheersandhth.-Alf 我相信你弄错了,std::list 的删除和插入是 O(1)。移位将发生在 std::vector 等顺序容器上。
  • @fish: std::remove_if 不会删除元素,它会移动或交换它们(也称为移位)。
  • @fish:您可以尝试一下,删除对(不存在的)std::erase 的调用。在发表评论之前尝试一下是个好主意。
【解决方案2】:

您不能在基于范围的 for 循环中擦除标准容器的元素,该循环在该容器上进行 - 循环本身具有您当前正在访问的元素的迭代器,并且擦除它会使循环之前的迭代器无效增加它。

基于范围的 for 在标准的 6.5.4 中定义为等效于(稍微简化):

for (auto __begin=begin-expr, __end=end-expr; __begin != __end; ++__begin) {
    for-range-declaration = *__begin;
    statement
}

begin-exprend-expr 有自己的冗长定义,但在您的示例中,它们分别是 myList.begin()myList.end()

【讨论】:

    【解决方案3】:

    不,我不这么认为。见this SO answer:

    不,你不能。基于范围的 for 是当您需要访问每个 容器的元素一次。

    如果需要,您应该使用普通的 for 循环或其表亲之一 要随时修改容器,请访问一个元素 一次,或者以非线性方式迭代 容器。

    【讨论】:

      猜你喜欢
      • 2013-08-25
      • 1970-01-01
      • 2011-07-13
      • 1970-01-01
      • 2019-09-09
      • 1970-01-01
      • 2016-11-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多