为什么 std::set 中的项目不能是 'popped'?

Why cant items from std::set be 'popped'?

我知道 std::set 不允许非常量访问它的项目。我知道不可能 项目移出集合——因为任何类型的非常量访问都可能破坏集合的顺序。

但是,我们可以从集合中删除一个项目。这不会破坏它,因为它只是迫使集合进行重组。那么,为什么我们不能 'pop' 一个项目?为什么我不能同时取出项目并擦除它?

我问的原因是 - 我需要一个订购的 unique_ptrs 容器。有时我需要从一个容器中 'pop' unique_ptrs 并将它们转移到另一个容器中。它们必须是我制作的自定义仿函数。

我不明白为什么不允许弹出功能?

要从 std::set 中提取节点,您可以使用 extract(...) 成员函数,该函数是在 C++17 中引入的:

#include <set>
#include <iostream>

int main()
{
    std::set<int> set{1, 5, 3, 7, 2};

    std::cout << "Original set: ";
    for (auto e : set)
        std::cout << e << ' ';
    std::cout << '\n';

    auto first = set.extract(set.begin());
    std::cout << "Extracted value: " << first.value() << '\n';

    std::cout << "New set: ";
    for (auto e : set)
        std::cout << e << ' ';
    std::cout << '\n';
}

输出:

Original set: 1 2 3 5 7
Extracted value: 1
New set: 2 3 5 7

这是对 pop() 在 C++ 中的作用的误解。例如,stack::pop() 删除堆栈的顶部元素,但它 而不是 return 它的副本。 那是因为被 returned 的类型的复制构造函数可能会抛出异常,如果发生这种情况,该对象就已经从堆栈中移除,因此无法恢复它。所以习惯用法是用stack::top()获取对顶层元素的引用并复制它,然后用stack::pop()移除它。

集合也一样:如果您将擦除元素与 return 复制它相结合,您会 运行 有丢失它的风险。