这段代码出现了 Visual Studio 的 error C3892
错误。如果我将 std::set
更改为 std::vector
,它就能正常工作。
std::set<int> a;
a.erase(std::remove_if(a.begin(), a.end(), [](int item)
{
return item == 10;
}), a.end());
怎么回事?为什么我不能在std::set
中使用std::remove_if
?
这段代码出现了 Visual Studio 的 error C3892
错误。如果我将 std::set
更改为 std::vector
,它就能正常工作。
std::set<int> a;
a.erase(std::remove_if(a.begin(), a.end(), [](int item)
{
return item == 10;
}), a.end());
怎么回事?为什么我不能在std::set
中使用std::remove_if
?
您不能使用std::remove_if()
处理具有const
部分的序列。 std::set<T>
元素的顺序由T const
对象组成。实际上,昨天我们在标准C++委员会中讨论了这个问题,并且支持创建专门处理从容器中erase()
对象的算法。它看起来像这样(也请参见N4009):
template <class T, class Comp, class Alloc, class Predicate>
void discard_if(std::set<T, Comp, Alloc>& c, Predicate pred) {
for (auto it{c.begin()}, end{c.end()}; it != end; ) {
if (pred(*it)) {
it = c.erase(it);
}
else {
++it;
}
}
}
它可能实际上会委托给一个算法,将逻辑分派到上面的逻辑中,因为相同的逻辑对于其他基于节点的容器也是相同的。
对于您特定的用途,您可以使用
a.erase(10);
a.erase(10)
可以利用 std::set<int>
的结构,并且时间复杂度为 O(log N),而算法的时间复杂度为 O(N)(其中 N == s.size()
)。从C++20开始,您可以针对具有 erase()
方法的容器使用std::erase_if,就像Kühl解释的那样。
// C++20 example:
std::erase_if(setUserSelection, [](auto& pObject) {
return !pObject->isSelectable();
});
std::vector
,因为它有一个erase方法。不再需要链式调用a.erase(std::remove_if(...
:)std::remove_if
会重新排列元素,因此不能与 std::set
一起使用。但是你可以使用 std::set::erase
:
std::set<int> a;
a.erase(10);
std::set
是有序的,而且它的排序是为了实现对数级别的查找(它是一棵二叉搜索树)。因此它与复杂度有关。 - juanchopanzastd::set
的元素顺序是由比较函数预先确定的,您无法更改顺序,否则容器将无法正常工作。 - Erbureth