简体   繁体   English

从std :: vector中删除迭代器

[英]Remove by iterator from std::vector

For removing an iterator from std::vector I can do these two things: 要从std::vector删除迭代器,我可以做以下两件事:

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

Or I can do this: 或者我可以这样做:

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

The second is more intuitive, I guess, but which one is faster? 我想,第二个更直观,但哪一个更快?

EDIT: Elements in vector are unique and we don't have to worry to delete several elements at once. 编辑:向量中的元素是唯一的,我们不必担心一次删除几个元素。

The first one is guaranteed to work correctly, while your second version may be faster (due to std::find stopping at the first item that matches), but it certainly is not safer. 第一个版本保证正常工作,而你的第二个版本可能更快(由于std::find停止在匹配的第一个项目),但它肯定不是更安全。

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

That would ensure you are not erasing an invalid iterator. 这将确保您不会删除无效的迭代器。

So it depends on your needs. 所以这取决于你的需求。 If you want a program that is correct, the first one works without further intervention, however the second requires a bug ticket from your customer and then you have to go fix it (as above). 如果你想要一个正确的程序,第一个程序可以在没有进一步干预的情况下工作,但是第二个需要来自客户的错误票,然后你必须去修复它(如上所述)。

The second is faster - the first will try to find all of elements which are equal to number_in , although it has already found one. 第二个是更快 - 第一个将尝试找到所有等于number_in的元素,尽管它已经找到了一个。 However, the second will stop when it find one. 但是,第二个会在找到一个时停止。

std::vector::erase 的std ::矢量::擦除

  • Removes the element at pos. 移除pos处的元素。

  • Removes the elements in the range [first; 删除范围内的元素[first; last). 持续)。

    Invalidates iterators and references at or after the point of the erase, including the end() iterator. 在擦除点或之后使迭代器和引用无效,包括end()迭代器。 The iterator pos must be valid and dereferenceable. 迭代器pos必须是有效且可解除引用的。 Thus the end() iterator (which is valid, but is not dereferencable) cannot be used as a value for pos. 因此,end()迭代器(有效但不可解除引用)不能用作pos的值。 The iterator first does not need to be dereferenceable if first==last: erasing an empty range is a no-op. 如果first == last,迭代器首先不需要是可解除引用的:擦除空范围是无操作。

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

The first approach would be slower since the entire vector will be searched for the number. 第一种方法会更慢,因为将搜索整个向量的数字。 But it is also the safer way. 但它也是更安全的方式。 Consider number_in is not an element of your vector. 考虑number_in不是向量的元素。 The first approach would try to erase an empty range which is defined and safe. 第一种方法是尝试擦除定义且安全的空范围。 And the second approach would try to erase the end iterator of your vector which is unsafe and UB. 第二种方法会尝试擦除不安全和UB的向量的结束迭代器。

It appears that you're interested in performance . 您似乎对性能感兴趣。 Finding the (first) matching element cannot be done faster than O(n) . 找到(第一个)匹配元素不能比O(n)更快地完成。 So, the part where you can try to improve performance is the removal, which can be O(1) , if you allow the order of the vector elements to change. 因此, 如果允许向量元素的顺序发生更改, 可以尝试提高性能的部分是删除,可以是O(1) For example 例如

// 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();
}

Note that solutions using std::remove() and/or vector::erase() will preserve the order of the remaining elements and hence inevitable still compact the remaining elements (quoted from comment by Tony D), which is almost always more expensive than finding the matching element and hence dominates the computational costs. 请注意,使用std::remove()和/或vector::erase()解决方案将保留其余元素的顺序,因此不可避免地仍然会压缩其余元素 (引自Tony D的评论),这几乎总是更昂贵而不是找到匹配元素,因此支配计算成本。

Just try which solution is faster – the proof of the pudding is in the eating! 试试哪种解决方案更快 - 布丁的证据就在吃!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM