是否有可能使multi_index容器使用连续的内存?

时间:2016-06-02 08:50:32

标签: c++ memory boost-multi-index

这里我有一个简单的multi_index容器,我想知道是否有任何方法可以强制multi_index在内存中连续分配元素。我认为如果主索引是random_access,这将是可能的。

然而,这个简单的例子表明,这些元素在内存中并不连续。 boost::multi_index::indexed_by的组合是否会导致连续的记忆?

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

int main(){
    typedef boost::multi_index_container<
        double,  // simply store doubles
        boost::multi_index::indexed_by<
            boost::multi_index::random_access<>
        >
    > random_access_container;

    random_access_container v; // fill container
    v.reserve(10); // also tried this
    v.push_back(1.);
    v.push_back(2.);
    v.push_back(3.);

    assert( v[0] == 1. ); // ok
    assert( *(&v[0] + 1) == v[1] ); // this fails, memory is not contiguous
}

注意1:我希望这是为了兼容性(所以我可以利用multi_index容器 - 与其他访问选项 - )但也可以使用直接内存访问(就像std::vector一样)。

注2:我刚从文档http://www.boost.org/doc/libs/1_61_0/libs/multi_index/doc/reference/rnd_indices.html#rnd_indices中找到了这个引用,所以看起来很难。

  

除非另有说明或相应的界面不存在,   随机访问索引验证相同的容器要求   std :: vector加上std :: list特定列表的要求   [list.ops]的操作。一些最重要的区别   对std :: vector的尊重是:

     
      
  1. 随机访问索引不提供内存连续性,因此没有数据成员函数。

         

    ...

  2.   

1 个答案:

答案 0 :(得分:2)

不,你没有记忆连续性。随机访问索引的布局类似于boost::container::stable_vector

的布局

random-access index memory layout

如果将元素(类型为T)存储在std::vector<T>中,然后使用multi_index_container std::ref<T> s,则可以获得连续内存的近似值。当然,这会使对象生命周期管理变得复杂。

编辑:设计理由

在库的设计中难以/难以包含内存连续性的原因有很多:

  • 迭代器稳定性由所有索引提供,而不仅仅是随机访问索引。如果元素连续存储在一块内存中,就不可能保持这种(具有合理的性能)。
  • 假设我们以某种方式设法获得随机访问索引诱导与元素存储相关的内存连续性。如果我们有两个随机访问索引会发生什么?似乎容器的第一个索引应该具有特殊的状态,以指示整个容器的布局以保持水。
  • 非随机访问索引必然是基于节点的。这意味着每个值都存储在一个更大的结构中,并有额外的信息空间(rb-tree指针等)。如果元素是连续存储的,则a)它是连续存储的节点,而不是值本身,这看起来很无用(想想data()会返回什么),或者b)节点必须与值分离,以便不是在节点中嵌入值而是我们有节点指向节点连续存储的值,这是浪费空间,看起来不像是一个合理的默认决定。