STL Container插入元素和内存透视
这个问题是 问题 的扩展,我想了解如何将元素插入 STL容器
。
假设我有一个对象;
,我想将其插入到任何STL容器
中,我知道有一个分配器
的概念来处理记忆。但我无法理解实际对象是如何复制到STL内存
中的。因此,当我调用Container.insert
时,我的对象
存储在堆栈
上,STL如何创建该对象的副本并将该对象存储到其内存中。
任何模拟相同内容的等效 C++ 代码都会有所帮助。
This question is extension of the question I want to understand how the elements are inserted into the STL Container
.
Suppose I have A object;
, which I want to insert into any of the STL Container
, I understand that there is concept of allocators
which handles the memory. But I fail to understand that how the actual object is copied into STL memory
. So my object
is stored on the stack
when I call Container.insert
how does STL create copy of this object and stored this objects into its memory.
Any equivalent C++
code would be helpful which simulates the same.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
该方法并不复杂。基本上,容器将从分配器获取内存,然后执行复制构造(在该内存上使用placement-new)。更容易看到的容器是
vector
:其中
ensure_enough_capacity()
确定向量是否必须增长并执行此操作,也就是说,如果,它将最终调用分配器>size()==capacity()
当push_back
被调用时。下一个复杂级别是列表,其中每个节点都是单独分配的,并且库必须管理一些额外的信息。在这种情况下,代码将类似于:
其中
x
和y
是初始化节点的next
和last< 的适当指针/code> 指针(对于
last
通常是指向最后一个节点的指针,对于next
则是指向哨兵节点的指针——超出末尾无效),以及假设这个特定的构造函数将复制构造值
,然后修复所有引用的指针。有序关联容器在管理平衡树方面具有额外的复杂性,但方法是相同的:分配一个足够大的块来容纳值和额外信息,然后使用placement-new来构建节点。剩下的就是数据结构的细节了。
The approach is not that complicated. Basically the container will obtain memory from the allocator and then perform copy-construction (with placement-new over that memory). The easier container to see is
vector
:Where
ensure_enough_capacity()
determines whether the vector has to grow and does it, that is, it will end up calling the allocator ifsize()==capacity()
whenpush_back
is called.The next level of complexity is a
list
, where each node is allocated on its own, and there is some extra information that the library has to manage. In that case the code would look similar to:Where
x
andy
are the appropriate pointers to initialize the node'snext
andlast
pointers (usually would be a pointer to the last node forlast
and a pointer to a sentry node --invalid beyond the end-- fornext
), and assuming that this particular constructor will copy-construct thevalue
and then fix all referred pointers.Ordered associative containers have the extra level of complexity of managing the balanced tree, but the approach is the same: allocate a block big enough to hold the value and the extra information, and then use placement-new to build the node. The rest are details of the data structure.
使用适当的复制构造函数(或者可能是 C++11 中的移动构造函数)复制对象。假设您已预先分配了一个包含 N 个
Foo
对象的数组,并且其中已有length
对象,则std::vector
中的代码可能会看起来像:new后面的括号表示“placement new”,即在预分配的存储上调用new。
The object is copied using the appropriate copy constructor (or, maybe, the move constructor in C++11). Assume that you have pre-allocated an array of N
Foo
objects and havelength
objects already in it, the code instd::vector
might look like:The brackets after the new indicate "placement new", that is, calling new on pre-allocated storage.
大多数插入函数的原型都是
采用
cost&
本质上是一种传递值而不将其复制到形式参数的方法。容器 - 取决于它们的工作方式 - 具有包含
A
的内部结构。例如,一个列表有一个
Insert,此时不只需要注意
该引用通过节点构造函数传递并传递给节点嵌入的 A 的初始值设定项,即它自己的复制构造函数。
请注意,allocator.allocate() 实际上必须为节点分配空间,而不仅仅是 A。因此,列表中的分配器实例的类型将是
typename Allocator::rebind::other
,其中Allocator
是list
的第二个模板参数,默认为std::allocator
。The most of the insert functions are prototyped as
Taking a
cost&
is -essentially- a way to pass a value without copy it in to the formal parameter.Container -depending on how they work- have an internal structure that contains
A
s.For example, a list has a
Insert, at that point does noting more than
The reference is passed through the node constructor and given to the initializer for the node's embedded A, that's its own copy constructor.
Note that allocator.allocate() atually has to allocate space for node, not just A. For that reason the allocator instance inside the list will be of type
typename Allocator::rebind<node>::other
, whereAllocator
is the second template parameter oflist
, that defaults tostd::allocator<A>
.内存分配方面真正发生的情况是:_it 使用作为
allocator
模板参数传入的分配器。无论您做什么
myAllocator
,它的分配(如果有)都将被使用。从技术上讲,这意味着您可以预先分配所有对(可能来自向量)。它还意味着正在使用新的放置,就像在向量情况下一样,只是,对于小分配,您的分配将被多次调用,而不是单个连续分配。这只会导致容器无法保证存储是连续的(就像向量情况一样),但是,由于实现的原因,它可能仍然是连续的 编写分配器
是一个高级主题,已在
https://github.com/paulhodge/EASTL
what really happens in terms of memory allocation is this: _it uses the allocator passed in as the
allocator
template parameter.whatever you make
myAllocator
do it's allocations from (if any) will be used. This technically means that you could preallocate all the pairs (perhaps from a vector). It also implicates that placement new is being used, just like in the vector case, only that, instead of a single contiguous allocation, your allocation will be called many times for small allocations.This only leads to the situation where the container cannot guarantee that storage is contiguous (like in the vector case), however, it miht still happen to be contiguous due to the implementation of your allocator
Writing allocators is an advanced topic and it has been addressed in
https://github.com/paulhodge/EASTL