std::remove_if无法正常工作

5

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

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个回答

18

std::remove_if 重新排列了向量的元素,使你想保留的元素在范围[vec.begin(), return_iterator)内(请注意部分开放范围)。因此,您需要调用std::vector::erase确保向量仅包含所需的元素。这被称为erase-remove习语

auto it = remove_if(vec.begin(),
                    vec.end(),
                    [](foo & f) { return f.release() == true; });

vec.erase(it, vec.end());

这里我为了清晰起见将其拆分成两行,但通常它会被视为单行。


2
std::removestd::remove_if并不实际删除任何元素,只是提供了一个迭代器,通过这个迭代器,您可以使用所使用的容器的适当成员函数来擦除元素。在std::vector的情况下,使用erase

我邀请您阅读Scott Meyers的这篇旧文章:"My Most Important C++ Aha! Moments...Ever"

当我发现将remove应用于容器时从不更改容器中的元素数量时,我感到震惊和背叛感,即使您要求它删除所有内容。欺诈!欺骗!虚假广告!


1
因为remove_if算法作用于两个前向迭代器所表示的元素范围,它不知道底层的容器或集合。

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

剩余的元素保持在有效但未指定的状态。完成此操作后,remove返回一个指向最后一个未删除元素之后的迭代器。

要从容器中实际消除元素,应将remove与容器的erase成员函数结合使用(因此称为“擦除-移除惯用语”)。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接