假设您想要按值从矢量中删除单个元素。 remove - 擦除:
之间有什么区别?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 :(得分: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
对你没用,因为它不会保留(其他)5s。如果你想要将非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和另一个一样好,你可以通过删除5s中的最后一个而不是第一个得到相同的结果,并且当它们不止一个时更有效:
auto it = partition(v.begin(), v.end(), [](int i) { return i != 5; });
if (it != v.end()) v.pop_back();
如果你能以某种方式确定向量最初包含完全一个等于5的元素(不多或少),那么你的两位代码就会做同样的事情。在这种情况下,您不需要在查找 - 擦除代码中对it != v.end()
进行测试,您会知道它不相等。你可以v.erase(find(v.begin(), v.end(), 5))
。
答案 1 :(得分:1)
不同之处在于,如果有多个值匹配给定的值,remove
解决方案会将所有不匹配的项目移动到开头(感谢Steve Jessop指出它在评论)。只有erase
才会删除这些内容的第一次出现;最后你得到一个重新排序的vector
,其中包含一个给定值的一个。
find
- 解决方案只会删除第一次出现,而不会更改向量的顺序。
答案 2 :(得分:-1)
你真的试着看到差异吗?
在第一段代码中,std::remove
通过将 all 等于5的元素放到向量的末尾并将迭代器返回到来转换向量新的结束。当您致电erase
时,您将删除新结束后的第一个元素。你可能想这样做:
vector<int>::iterator it = remove(v.begin(), v.end(), 5);
v.erase(it, v.end());
这将删除值为5的所有元素。
在第二个例子中,std::find
找到向量的第一个元素,它等于5并返回一个迭代器。调用erase
只会删除该元素。
这就是区别。