【问题标题】:boost multi_index_container changing keys -> incorret state of container提升 multi_index_container 更改键 -> 容器状态不正确
【发布时间】:2013-07-25 11:52:51
【问题描述】:

假设我们有一个多索引容器:

#include <iostream>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/tag.hpp>
#include <boost/multi_index/key_extractors.hpp>

struct A{
A(int i){id=i;}
    int id;
};

typedef boost::multi_index::multi_index_container<
    A * ,
    boost::multi_index::indexed_by<
        boost::multi_index::random_access<
            boost::multi_index::tag<by_insertion>
        >, // this index represents insertion order
        boost::multi_index::hashed_unique<
            boost::multi_index::tag<by_id>,
            boost::multi_index::member<A, int, &A::id>
        >
    >
> MapType;

MapType map;

map.get<1>().insert(new A(1));
map.get<1>().insert(new A(2));

(*map.get<1>().find(1))->id=4; // HERE IF I CHANGE THE KEY, I CAN NOT FIND either key=4 or 1

MapType::nth_index<1>::type::iterator it = map.get<1>().find(4);
if(it != map.get<1>().end() ){
    std::cout << "FOUND A:" << *it << std::endl;
} // DOES NOT WORK?? WHY CANT I FIND the ELement with Key 4?

现在的问题是我可能错误地设置了boost::multi_index::member&lt;A, int, &amp;A::a&gt;,因为当我更改了一些键时。我找不到 key = 4 的元素?

这里用错了什么? 任何帮助都非常感谢!

【问题讨论】:

  • 等一下:您是否正在更改您在地图中查找的值,并期望地图神奇地知道这一点?通常,在不通知容器的情况下更改容器中的“正在查找的事物”会导致 UB。

标签: c++ boost map key boost-multi-index


【解决方案1】:

不,散列索引不存储散列值,它们总是即时计算。为什么要更改键,但仍要按旧值查找?

【讨论】:

  • 那么为什么我找不到 key = 4 MapType::nth_index&lt;1&gt;::type::iterator it = map.get&lt;1&gt;().find(4); if(it != map.get&lt;1&gt;().end() ){ std::cout &lt;&lt; "FOUND A:" &lt;&lt; *it &lt;&lt; std::endl; } 的元素这不起作用!
  • 因为元素被存储为好像 key = 1。发生的事情是: * 如果你寻找 4,你最终会进入一个空桶。 * 如果您查找 1,您会发现该元素,但在检查键时这是 4,因此查找也会失败。
  • 还有,重复我的问题:你为什么要这样做?
  • 感谢您的精彩解释!我不想更改密钥,但根本问题是,如果我只将指针放入容器中,那么我就可以更改元素(容器只有读取访问权限,使所有 A* const 类型的引用迭代器在可能的情况下更改 A 的底层实例),但随后我可以更改基于容器的键,只要该键在 A 类中不是常量。这不愚蠢吗?
【解决方案2】:

回答 Gabriel 的最后一条评论:使用指针容器只是为了拥有对元素的写访问权限是多余的。您可以执行以下操作之一:

  • 使用modify(),它会检查修改后的元素是否因触摸了某个键而必须重新定位。
  • 如果您知道自己不会更改密钥,请使用const_cast&lt;A&amp;&gt;() 投射并随意修改。

一般来说,Boost.MultiIndex 无法仅授予对元素的非关键部分的写访问权限。

【讨论】:

  • 耶,抱歉我的误导性描述:我想在这个容器中有指针,我这样做不是为了能够更改对象。这有点微妙,但在我上面的测试中,我偶尔会绕过这样一个事实,即容器应该只授予它所做的 const 访问,但对指针没有影响。所以有我的问题。我的密钥无论如何都需要在类中保持不变const A::id,所以指向A 的指针是可以的。使用 modify() 是一种选择,但有点麻烦。
  • 另一种方法是在新类Data 中收集指向Akey 的指针
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-20
  • 1970-01-01
相关资源
最近更新 更多