您的删除-擦除代码不正确。 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))。