3

这是我的代码。我想从向量中删除所有成功调用方法“释放”的元素。

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运作?

4

4 回答 4

14

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

在这里,为了清楚起见,我将它分成两行,但它通常被视为单行。

于 2014-03-29T10:40:14.317 回答
1

std::remove并且std::remove_if实际上并没有删除任何东西,只是给你一个迭代器,然后你可以使用你使用的任何容器的适当成员函数来擦除元素。在std::vector的情况下,erase

我邀请您阅读 Scott Meyers 的这篇旧文章:“我最重要的 C++ 啊哈!时刻......永远

因此,带着相当大的震惊和背叛的感觉,我发现对容器应用 remove 永远不会改变容器中元素的数量,即使你要求它删除所有内容也不会。欺诈罪!欺骗!虚假广告!

于 2014-03-29T10:41:14.480 回答
1

因为该remove_if算法对由两个前向迭代器表示的一系列元素进行操作,所以它不了解底层容器或集合。

因此,实际上没有从容器中删除任何元素。相反,所有不符合删除条件的元素都以相同的相对顺序放在范围的前面。

其余元素处于有效但未指定的状态。完成后,remove 返回一个迭代器,该迭代器指向最后一个未删除元素之后的一个元素。

要真正从容器中删除元素,remove 应该与容器的erase成员函数结合使用(因此命名为“erase-remove idiom”)。

于 2014-03-29T10:39:24.277 回答
0

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());
于 2014-03-29T10:42:03.457 回答