【问题标题】:Alternative to std::set (with ability to move elements from one set to another)std::set 的替代方案(能够将元素从一个集合移动到另一个集合)
【发布时间】:2012-12-14 09:57:01
【问题描述】:

我正在寻找std::set 的替代品。我需要它来支持更多的操作然后std::set:

  1. 将元素从一个集合移动到另一个集合,无需“create new->copy->remove old”。

  2. 在某个位置拆分集合得到两个集合(使用std::list splice可以获得类似的行为)

  3. 设置操作(如联合),无需不必要的复制。 std::set_union 会将元素从集合 A 和 B 复制到集合 C,如果我只需要集合 C 而不再需要 A 和 B,这将是低效的。

是否有任何支持这些操作的实现,或者我需要自己编写一个?

【问题讨论】:

  • 你想要的不是std::set 的替代品,而是更多的算法在集合上工作。感谢完全透明的 C++ 容器和算法库的设计。您可以添加算法而无需更改数据结构。至于第一点,可以使用std::move
  • @KonradRudolph, set 迭代器是 const 以防止您使密钥无效。如果移出的元素改变了值(这很可能),它在集合中的位置将需要改变。您需要非常小心地移动元素,然后立即通过迭代器将其擦除,这样在移动后不会检查该值
  • 糟糕,我的意思是说“即使你抛弃了 const,你也需要非常小心......”
  • @JonathanWakely 好吧,我的回答中实际上暗示了“移动,然后擦除”,因为显然该元素不再有效。
  • 但不仅仅是erase(key),它必须是erase(iter),因为前者试图找到元素,并且在破坏排序不变式时搜索set将不起作用。基本上它属于未定义行为的领域

标签: c++ stl set


【解决方案1】:

std::set 我和你有同样的问题,而且 C++11、C++14 似乎没有任何理智的方法。然而,在 C++17 中,std::set 添加了两个新成员,看起来很有希望。 std::set::extract 允许从集合中提取整个节点。移除的节点允许获得对基础值的非常量引用,从而有效地允许将元素移出集合。它也可以插入到另一个集合中,而无需复制或移动基础值。 std::set::merge 允许合并两个集合而不复制或移动任何元素,只更新内部指针。

【讨论】:

    【解决方案2】:

    尝试使用std::set 执行您的建议的问题在于,我不相信您可以将值移出一个值。这是因为设置迭代器只返回 const 引用以阻止您更改值并破坏内部结构。您可能可以const_cast 解决这个问题,但我不推荐它。即使您采用这种方法,您仍然在树中分配了节点,您无法采取任何措施来避免这种开销。

    如果您决定实现自己的支持移动值的集合,您应该能够获得 Boost::Intrusive 库 (http://www.boost.org/doc/libs/1_52_0/doc/html/ intrusive.html) 来完成保持一组排序值的繁重工作。您需要实现用于管理对象生命周期的代码,但这比构建 RB-tree 实现更容易。

    我为将节点存储在std::list 中的地图实现了类似的功能。这允许在地图之间移动元素,而无需复制节点结构或存储的值。如果我有时间,我会尝试整理并在此处发布。

    【讨论】:

      【解决方案3】:

      对于第 1 点和第 3 点,您可以使用 set<shared_ptr> 或其他一些智能指针,而不是直接在 set 中存储对象。在这种情况下,你应该实现

      bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b)
      

      对于第 2 点,不会有这种仅由索引确定的方法,因为set 中没有索引。但是,您可以在 ruby​​ 中使用 filter 之类的东西。这里的谓词可以是函数、函数对象或闭包。

      remove_copy_if(foo.begin(), foo.end(), back_inserter(bar), some_predicator);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-02-28
        • 2015-01-18
        • 1970-01-01
        • 2021-12-04
        • 1970-01-01
        • 1970-01-01
        • 2020-03-22
        相关资源
        最近更新 更多