这是我的代码。我想从向量中删除所有成功调用方法“释放”的元素。
bool foo::release()
{
return true;
}
// ...
vector<foo> vec;
// ...
remove_if(vec.begin(), vec.end(), [](foo & f) { return f.release() == true; });
// ...
但remove_if
不是从vector vec
. 如何remove_if
运作?
std::remove_if
重新排列向量的元素,使您想要保留的元素在范围内[vec.begin(), return_iterator)
(注意部分开放的范围)。因此,您需要调用std::vector::erase
以确保向量仅包含所需的元素。这称为擦除删除习语:
auto it = remove_if(vec.begin(),
vec.end(),
[](foo & f) { return f.release() == true; });
vec.erase(it, vec.end());
在这里,为了清楚起见,我将它分成两行,但它通常被视为单行。
std::remove
并且std::remove_if
实际上并没有删除任何东西,只是给你一个迭代器,然后你可以使用你使用的任何容器的适当成员函数来擦除元素。在std::vector
的情况下,erase
。
我邀请您阅读 Scott Meyers 的这篇旧文章:“我最重要的 C++ 啊哈!时刻......永远”:
因此,带着相当大的震惊和背叛的感觉,我发现对容器应用 remove 永远不会改变容器中元素的数量,即使你要求它删除所有内容也不会。欺诈罪!欺骗!虚假广告!
因为该remove_if
算法对由两个前向迭代器表示的一系列元素进行操作,所以它不了解底层容器或集合。
因此,实际上没有从容器中删除任何元素。相反,所有不符合删除条件的元素都以相同的相对顺序放在范围的前面。
其余元素处于有效但未指定的状态。完成后,remove 返回一个迭代器,该迭代器指向最后一个未删除元素之后的一个元素。
要真正从容器中删除元素,remove 应该与容器的erase
成员函数结合使用(因此命名为“erase-remove idiom”)。
见http://en.wikipedia.org/wiki/Erase-remove_idiom
std::remove_if
实际上并没有消除擦除元素。它所做的是将满足条件的元素移动到范围的末尾。然后它返回一个迭代器,指向已删除(实际上只是移动)元素的第一个元素。然后,您可以从容器中删除该范围。
vector<foo> vec;
auto remove_start = remove_if(vec.begin(), vec.end(), [](foo & f) { return f.release() == true; });
vec.erase(remove_start, vec.end());
或者
vec.erase(remove_if(vec.begin(), vec.end(),
[](foo & f) { return f.release() == true; }),
vec.end());