【问题标题】:How to move an element without removing and re-inserting it into a boost::multi_index_container?如何在不移除元素并将其重新插入到 boost::multi_index_container 的情况下移动元素?
【发布时间】:2011-07-06 00:48:14
【问题描述】:

我正在使用boost::multi_index_container 提供对元素集合的随机访问和基于散列的访问。我想改变一个元素的随机访问索引,而不改变基于哈希的索引。

这是一段代码:

# include <string>
# include <boost/multi_index_container.hpp>
# include <boost/multi_index/random_access_index.hpp>
# include <boost/multi_index/hashed_index.hpp>
# include <boost/multi_index/member.hpp>

using namespace std ;
using namespace boost ;
using namespace boost::multi_index ;

// class representing my elements
class Element
{
    public :
      Element(const string & new_key) : key(new_key) {}
      string key ;      // the hash-based index in the multi_index_container
      // ... many stuff skipped
    private :
      // ... many stuff skipped
} ;

typedef multi_index_container<
            Element,
            indexed_by<
                random_access< >,
                hashed_unique<
                    member<Element, string, &Element::key>
                >
            >    
        > ElementContainer ;

typedef ElementContainer::nth_index<0>::type::iterator ElementRandomIter ;
typedef ElementContainer::nth_index<1>::type::iterator ElementHashedIter ;

int main(int, char*[])
{
    ElementContainer ec ;

    // insert some elements
    ec.push_back(Element("Alice")) ;       // random-access index = 0
    ec.push_back(Element("Bob")) ;         // random-access index = 1
    ec.push_back(Element("Carl")) ;        // random-access index = 2
    ec.push_back(Element("Denis")) ;       // random-access index = 3

    // Here I want to move "Denis" to position 1
    // The (bad looking) solution I found involves removing and inserting the element
    ElementRandomIter it = ec.get<0>().begin() + 3 ;
    Element e = *(it) ;                    // store a copy
    ec.get<0>().erase(it) ;                // remove the element
    it = ec.get<0>().begin() + 1 ;
    ec.get<0>().insert(it, e) ;            // insert the copy

    // Elements are now in the following order
    // random-access index 0 : Alice
    // random-access index 1 : Denis
    // random-access index 2 : Bob
    // random-access index 3 : Carl

    return 0 ;
}

我知道,即使我在此示例中仅使用随机访问迭代器来操作元素,在 multi_index_container 中至少会在幕后发生两次散列,此外还有对象副本,这可能会很昂贵。

有没有一种方法可以更改 boost::multi_index 内元素的随机访问索引,而不需要昂贵的删除和插入同时保持复制丑陋?

我在multi_index_container 文档中进行了搜索,也许我遗漏了一些东西。感谢您的建议!

注意:对于可能的英语错误,我们深表歉意:)

【问题讨论】:

    标签: c++ boost multi-index


    【解决方案1】:

    【讨论】:

    • 就是这样!我确定我错过了 multi_index 文档中的某些内容!
    【解决方案2】:

    使用modify_key怎么样?我以前做过类似的事情,虽然在我的情况下索引不是随机访问的,但我想它可能对你也有用。

    【讨论】:

    • 我想过,但modify_key 需要一个修饰符,它将接收要修改的元素,但在我的情况下,随机访问索引存储在multi_index_container 内,而不是内部Elements 的属性
    • 这是一个很好的观点。我之前一直在想这个问题。从根本上说,您的随机访问索引就像一个向量,所以我现在可以建议的最好方法是通过在擦除之前插入来消除您的两个复制操作之一。要么,要么停止使用随机访问索引。
    • 太棒了!感谢您的建议。对于我正在处理的数据结构,随机访问是强制性的。我还考虑让我的 Element 对象轻量级(通过引入一些写时复制机制)。
    • @overcoder :如果您使用的是 C++0x 编译器,那么让您的 Element 对象可移动就足够了,不需要 CoW。
    • 我忘了说哈希索引是唯一的。因此,如果不选择临时未使用的哈希索引,则在删除之前插入是不可能的。悲伤的消息...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    • 2014-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多