【问题标题】:What is the difference between remove-erase and find-eraseremove-erase 和 find-erase 有什么区别
【发布时间】:2013-11-15 11:26:04
【问题描述】:

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

【问题讨论】:

标签: c++ stl


【解决方案1】:

您的删除-擦除代码不正确。 remove-erase 习惯用法如下所示:

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

在这种情况下,它具有擦除所有等于 5 的值的效果,但它最大限度地减少了实现该目标所需的复制量。

您的查找-擦除代码仅删除等于 5 的第一个值,因此它会执行您想要的操作。

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

因此,如果您只想删除几个等于 5 的单个元素,那么 std::remove 对您没有用,因为它不会保留(其他)5。如果您想将非 5 值移到开头,将 5 值移到末尾,然后再删除 5 中的第一个,那么实际上您可以使用 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 而不是第一个来获得相同的结果,并且当有多个 5 时效率更高:

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))

【讨论】:

  • 嗯,很高兴提到标准擦除习语;但OP实际上只想要删除一个发生
【解决方案2】:

不同之处在于,如果有多个值匹配给定的值,remove 解决方案会将所有不匹配的项目移到开头(感谢 Steve Jessop 在 cmets 中指出) .只有erase 会删除第一次出现的这些;你最终会得到一个重新排序的vector,其中包含给定值的少一个。

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

【讨论】:

  • remove 不会将相等的值移动到末尾,而是将不相等的值移动到开头。最后剩下的内容未指定。
【解决方案3】:

您是否真的尝试过看到不同之处?

在第一段代码中,std::remove 通过将 all 等于 5 的元素放在向量末尾来转换向量,并将迭代器返回给 new结束。当您调用 erase 时,您将删除新结束后的第一个元素。您可能想要这样做:

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

这将删除所有值为 5 的元素。

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

这就是区别。

【讨论】:

  • 他调用的是单参数版本的擦除,所以只有一个元素被擦除。
  • 在第一段代码上调用erase只会删除第一个被删除的元素。
  • 是的,我注意到了,但是在我编辑答案时你们太快了
猜你喜欢
  • 2022-11-17
  • 2010-12-13
  • 2014-07-08
  • 2017-02-06
  • 1970-01-01
  • 2012-07-14
  • 2017-03-19
  • 2023-03-30
  • 2018-01-13
相关资源
最近更新 更多