这个问题是question的扩展我想了解元素如何插入STL Container
。
假设我有A object;
,我想插入STL Container
中的任何一个,我理解有allocators
概念来处理内存。但我不明白实际对象如何被复制到STL memory
。因此,当我调用object
时,我的stack
存储在Container.insert
上.STL如何创建此对象的副本并将此对象存储到其内存中。
任何等效的C++
代码都会有所帮助,模拟相同的代码。
答案 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 );
}
其中x
和y
是初始化节点的next
和last
指针的适当指针(通常是指向{{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 仍然恰好是连续的实现你的分配器
编写分配器是一个高级主题,它已在
中解决