STL容器插入元素和内存透视图

时间:2011-10-24 06:27:16

标签: c++ stl insert implementation containers

这个问题是question的扩展我想了解元素如何插入STL Container

假设我有A object;,我想插入STL Container中的任何一个,我理解有allocators概念来处理内存。但我不明白实际对象如何被复制到STL memory。因此,当我调用object时,我的stack存储在Container.insert上.STL如何创建此对象的副本并将此对象存储到其内存中。

任何等效的C++代码都会有所帮助,模拟相同的代码。

4 个答案:

答案 0 :(得分:3)

方法并不复杂。基本上,容器将从分配器获取内存,然后执行复制构造(在该内存中使用 placement-new )。容易看到的容器是vector

void push_back( T const & value ) {
   ensure_enough_capacity();
   new (end_ptr++) T( value );
}

ensure_enough_capacity()确定向量是否必须增长并执行此操作,也就是说,如果size()==capacity()被调用push_back,它将最终调用分配器。

下一级复杂性是list,其中每个节点都是自己分配的,并且库需要管理一些额外的信息。在这种情况下,代码看起来类似于:

void push_back( T const& value ) {
    node* n = allocator::allocate( sizeof(node) );
    new (n) node( value, x, y );
}

其中xy是初始化节点的nextlast指针的适当指针(通常是指向{{1}的最后一个节点的指针}和一个指向哨兵节点的指针 - 在last之后无效 - 并且假设这个特定的构造函数将 copy-construct next然后修复所有推荐的指针。

有序关联容器具有管理平衡树的额外复杂性,但方法是相同的:分配一个足够大的块来保存值和额外信息,然后使用 placement-new 构建节点。其余的是数据结构的细节。

答案 1 :(得分:0)

使用适当的复制构造函数(或者,可能是C ++ 11中的移动构造函数)复制对象。假设您已预先分配了一个N Foo个对象的数组,并且其中已包含length个对象,std::vector中的代码可能如下所示:

void std::vector<Foo>::push_back( const Foo& n ) { 
    new( my_memory+length ) Foo(n);
    ++length;
}

新的括号后面的括号表示“放置新的”,即在预先分配的存储空间中调用new。

答案 2 :(得分:0)

大多数插入函数原型为

void insert(const A& a);

cost&为基础 - 一种传递值的方法,而不将其复制到形式参数中。

容器 - 取决于它们的工作方式 - 具有包含A的内部结构。 例如,列表有

struct node
{
   A val;
   node* next;
   node* prev;

   node(const A& a) :val(a), next(), perv()
   { }  
};

插入,此时注意力超过

void insert(const A& a)
{
   node* n = new(allocator.allocate()) node(a);
   /*set next and prev accordingly to list functionality*/
}

引用通过节点构造函数传递给节点的嵌入式A的初始化器,这是它自己的复制构造函数。

请注意,allocator.allocate()通常必须为节点分配空间,而不仅仅是A.因此,列表中的分配器实例将是typename Allocator::rebind<node>::other类型,其中Allocator是第二个list的模板参数,默认为std::allocator<A>

答案 3 :(得分:0)

在内存分配方面真正发生的是:_it使用传入的分配器作为allocator模板参数。

 map<int , long , less<int> , myAllocator<pair<int, long> > > myMap;

无论你做什么myAllocator,都要使用(如果有的话)分配。这在技术上意味着您可以预分配所有对(可能来自向量)。它还表示正在使用placement new,就像在向量的情况下一样,只是,对于小分配,您的分配将被多次调用,而不是单个连续分配。

这只会导致容器无法保证存储是连续的(例如在矢量情况下),但是 miht 仍然恰好是连续的实现你的分配器

编写分配器是一个高级主题,它已在

中解决