2013-11-15 61 views
4

假设您想通过值从矢量中删除单个元素。是什么remove -erase之间的区别:删除 - 删除和查找 - 删除有什么区别

vector<int> v; 
// add some values 
vector<int>::iterator it = remove(v.begin(), v.end(), 5); 
v.erase(it); 

和查找删除

vector<int> v; 
// add some values 
vector<int>::iterator it = find(v.begin(), v.end(), 5); 
if(it != v.end()) 
{ 
    v.erase(it); 
} 
+0

[我在这里做了两个评论,但他们都错了,请忽略:-)] –

+0

更好的答案在这里提供:https://stackoverflow.com/questions/24011627/erasing-using-iterator-from-查找或删除 – giuseppe

回答

13

您的删除代码不正确。删除擦除成语看起来像这样:

vector<int>::iterator it = remove(v.begin(), v.end(), 5); 
v.erase(it, v.end()); 

在这种情况下,它具有擦除等于5的所有值的效果,但是它最小化拷贝以实现所需的量。

您的查找 - 删除代码只会删除第一个等于5的值,因此它会按照您的要求进行操作。

删除代码将所有不等于5的值移动到向量的前面(这就是std::remove的作用),擦除向量的剩余元素之一,并在其后留下任何其余元素,其中包含未指定的值(这也是remove所做的)。如果矢量首先不包含5,则它具有未定义的行为,因为在这种情况下,remove将返回v.end()

因此,如果您只想擦除几个等于5的单个元素,那么std::remove对您没有用处,因为它不保留(其他)5。如果你想在非5值开始和5个值移动到结束,去除第一的5S之前,那么你实际上可以做到这一点与std::partition只是不能与std::remove

auto it = partition(v.begin(), v.end(), [](int i) { return i != 5; }); 
if (it != v.end()) v.erase(it); 

虽然,因为一个5作为另一个您删除了最后的5秒,而不是第一个获得相同的结果,而且它的效率更高,当有超过其中一个是好的:

auto it = partition(v.begin(), v.end(), [](int i) { return i != 5; }); 
if (it != v.end()) v.pop_back(); 

如果你能以某种方式确保矢量最初包含正好一个元素等于5(没有更多或更少s),那么你的两个代码就会做同样的事情。在这种情况下,您不需要在查找 - 清除代码中对it != v.end()进行测试,您会知道它不相同。你可以做v.erase(find(v.begin(), v.end(), 5))

+0

时,你们太快了,很好的提到了标准的擦除习惯用法;但OP实际上只是**希望**删除**一个**发生 – codeling

1

所不同的是,如果有多个值匹配给定之一,remove解决方案将所有移动的非匹配项目的开始(感谢Steve Jessop在评论中指出)。然后只有erase将删除这些的第一次发生;最后得到一个重新排序的vector,其中包含一个给定值。

find - 解决方案只会删除第一次发生,而不会改变向量的顺序。

+0

'remove'不会将相等的值移动到末尾,它会将不相等的值移动到开头。最后剩下的是未指定的。 –

-1

您是否真的尝试了解区别?

在第一代码段,std::remove通过将所有中等于5到载体的端部的元件变换向量,并返回迭代器端。当你打电话给erase时,你会在新的结束后删除第一个元素。你可能想要做的:

vector<int>::iterator it = remove(v.begin(), v.end(), 5); 
v.erase(it, v.end()); 

这将删除所有与价值5

元素在第二个例子,std::find发现等于5向量的第一个元素,并返回一个迭代器它。调用erase只会删除该元素。

这是区别。

+0

他称之为擦除的单参数版本,因此只有一个元素被擦除。 –

+0

在第一段代码中调用'erase'将只擦除第一个被删除的元素。 – Snps

+0

是的,我注意到,但是当我编辑我的回答 –