remove-erase和find-erase之间有什么区别

时间:2013-11-15 11:26:04

标签: c++ stl

假设您想要按值从矢量中删除单个元素。 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);
}

3 个答案:

答案 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只会删除该元素。

这就是区别。