简体   繁体   English

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

[英]What is the difference between remove-erase and find-erase

Suppose you want to remove a single element from a vector by value. 假设您想要按值从向量中删除单个元素。 What is the difference between remove -erase: remove -erase有什么区别:

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

And find-erase 并找到 - 擦除

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

Your remove-erase code is not correct. 您的删除 - 删除代码不正确。 The remove-erase idiom looks like this: 删除 - 擦除习语看起来像这样:

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

In that case, it has the effect of erasing all values equal to 5 but it minimises the amount of copying required to achieve that. 在这种情况下,它具有擦除所有等于5的值的效果,但它最小化了实现该值所需的复制量。

Your find-erase code removes only the first value equal to 5, so it does what you want. 您的查找 - 擦除代码仅删除第一个等于5的值,因此它可以执行您想要的操作。

Your remove-erase code moves all the values not equal to 5 to the front of the vector (that's what std::remove does), erases one of the remaining elements of the vector, and leaves any remaining elements after that with unspecified values (which is also what remove does). 你的删除 - 擦除代码将所有不等于5的值移动到向量的前面(这就是std::remove所做的),擦除向量的其余元素之一,并在此之后留下任何剩余的元素,带有未指定的值(这也是什么remove )。 It has undefined behavior if the vector doesn't contain a 5 to begin with, because remove would return v.end() in that case. 如果向量不包含5开头,则它具有未定义的行为,因为在这种情况下remove将返回v.end()

So, if you only want to erase a single element of several equal to 5 then std::remove is no use to you because it doesn't preserve the (other) 5s. 所以,如果你只想删除几个等于5的单个元素,那么std::remove对你没用,因为它不保留(其他)5s。 If you want to move the non-5 values to the start and the 5 values to the end, before removing the first of the 5s, then you could in fact do that with std::partition just not with std::remove : 如果你想将非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);

Although, since one 5 is as good as another you get the same result by erasing the last of the 5s rather than the first, and it's more efficient when there's more than one of them: 虽然,因为一个5和另一个一样好,你可以通过删除5s中的最后一个而不是第一个得到相同的结果,并且当它们不止一个时更有效:

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

If you can somehow be sure that the vector initially contains exactly one element equal to 5 (no more or less), then your two bits of code do the same thing. 如果你能以某种肯定的是,最初载体包含一个元素等于5(没有更多或更少),那么代码的两位做同样的事情。 And in that case you wouldn't need the test for it != v.end() in the find-erase code, you would know it isn't equal. 在这种情况下,您不需要在查找 - 擦除代码中进行测试it != v.end() ,您会知道它不相等。 You could just do v.erase(find(v.begin(), v.end(), 5)) . 你可以做v.erase(find(v.begin(), v.end(), 5))

The difference would be that if there is more than one value matching the given one, the remove solution will move all of the non-matching items to the start (thanks to Steve Jessop for pointing it out in the comments). 不同之处在于,如果有多个值与给定值匹配,则remove解决方案会将所有不匹配的项目移动到开头(感谢Steve Jessop在评论中指出它)。 Only erase will then remove the first occurence of these; 只有erase才会消除这些的第一次出现; and you end up with a re-sorted vector , containing one less of the given value. 最后得到一个重新排序的vector ,包含少一个给定值。

The find - solution would only remove the first occurence, and not change the order of the vector. find解决方案只会删除第一次出现,而不会更改向量的顺序。

Did you actually try to see the difference? 你真的试着看到差异吗?

In the first piece of code, std::remove transforms the vector by placing all the elements that are equal to 5 to the end of the vector and returns the iterator to the new end. 在第一段代码中, std::remove通过将所有等于5的元素放到向量的末尾并将迭代器返回到新的末尾来转换向量。 When you call erase then you remove the first element after the new end. 当您调用erase时,您将erase新结束后的第一个元素。 You probably want to do: 你可能想做:

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

That would remove all the elements with value 5. 这将删除值为5的所有元素。

In the second example, std::find finds the first element of the vector that is equal to 5 and returns an iterator to it. 在第二个示例中, std::find查找向量的第一个元素,该元素等于5并返回一个迭代器。 Calling erase will only remove that element. 调用erase将仅删除该元素。

That is the difference. 这就是区别。

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

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