从std :: vector中删除迭代器

时间:2015-02-05 10:56:22

标签: c++ vector std

要从std::vector中删除迭代器,我可以做以下两件事:

std::vector<int>& vec = myNumbers; // use shorter name
vec.erase(std::remove(vec.begin(), vec.end(), number_in), vec.end());

或者我可以这样做:

auto it = find(vec.begin(), vec.end(), number_in);
vec.erase(it);

第二种更直观,我猜,但哪一种更快?

修改: 向量中的元素是唯一的,我们不必担心一次删除多个元素。

4 个答案:

答案 0 :(得分:2)

第一个版本保证正常工作,而第二个版本可能更快(由于std::find停在匹配的第一个项目上),但肯定不是更安全。

auto it = find(vec.begin(), vec.end(), number_in);
if (it != vec.end())
   vec.erase(it);

这样可以确保您没有删除无效的迭代器。

所以这取决于你的需求。如果你想要一个正确的程序,第一个程序可以在没有进一步干预的情况下工作,但是第二个程序需要来自客户的错误罚单,然后你必须修复它(如上所述)。

答案 1 :(得分:1)

第二个更快 - 第一个会尝试找到等于number_in所有元素,尽管它已经找到了一个。{但是,第二个会在找到它时停止。

答案 2 :(得分:1)

std :: vector :: erase

  
      
  • 删除pos处的元素。

  •   
  • 删除范围内的元素[first;最后一个)。

         

    在擦除点或之后使迭代器和引用无效,包括end()迭代器。   迭代器pos必须是有效且可解除引用的。因此,end()迭代器(有效但不可解除引用)不能用作   pos的值。   如果first == last,迭代器首先不需要可解除引用:删除空范围是无操作。

  •   

http://en.cppreference.com/w/cpp/container/vector/erase

第一种方法会慢一些,因为将搜索整个向量的数字。但它也是更安全的方式。考虑number_in不是向量的元素。第一种方法是尝试擦除定义且安全的空范围。第二种方法是尝试擦除不安全和UB的矢量的结束迭代器。

答案 3 :(得分:1)

您似乎对效果感兴趣。找到(第一个)匹配元素不能比O(n)更快地完成。因此,您可以尝试提高性能的部分是删除,可以是O(1)如果允许 要更改的向量元素的顺序。例如

// find requires up to O(n)
auto it = std::find(v.begin(),v.end(),value);
// remove in O(1) but don't preserve order
if(it!=v.end()) {
  std::iter_swap(it,--(v.end()));
  v.pop_back();
}

请注意,使用std::remove()和/或vector::erase()的解决方案将保留其余元素的顺序,因此不可避免的仍会压缩其余元素(引自Tony D的评论) ),这几乎总是比找到匹配元素更昂贵,因此支配计算成本。

试试哪种解决方案更快 - 布丁的证据就在吃!