STL Containers 分配放置新
我找不到这个问题的确切答案,因此在这里发布.当我想到向量时,它需要在连续的内存位置构建对象.这意味着向量保持分配的内存,并且必须对被推入其中的对象进行就地构造(=放置新).这是一个有效的假设吗?另外,这是否意味着容器正在手动调用析构函数而不是调用删除?我在这里缺少任何其他假设吗?这是否意味着我可以假设如果我选择编写,即使是为对象编写的自定义 new 也可能不会被调用?
I couldn't find an exact answer to this question and hence posting here. When I think of vector, it needs to build objects in a contiguous memory location. This means that vector keeps memory allocated and have to do an in-place construction (=placement new) of objects being pushed into it. Is this a valid assumption? Also, does this mean the container is manually invoking the destructor rather than calling delete? Are there any other assumptions that I am missing here? Does this mean I can assume that even a custom written new for the object may not be invoked if I chose to write?
此外,列表使用 new 和 delete 也是有意义的,因为我们不需要连续内存保证.那么,这种行为是驱动分配器行为的原因吗?请帮忙.谢谢
Also it makes sense for a list to use a new and delete as we don't need the continuous memory guarantee. So, is this kind of behavior is what drives how allocators behave? Please help. Thanks
推荐答案
这意味着 vector 保持分配的内存,并且必须对被推入其中的对象进行就地构造(=placement new).这是一个有效的假设吗?
This means that vector keeps memory allocated and have to do an in-place construction (=placement new) of objects being pushed into it. Is this a valid assumption?
是的
另外,这是否意味着容器是手动调用析构函数而不是调用delete?
Also, does this mean the container is manually invoking the destructor rather than calling delete?
是的
我在这里是否缺少任何其他假设?这是否意味着我可以假设如果我选择编写,即使是为对象编写的自定义 new 也可能不会被调用?
Are there any other assumptions that I am missing here? Does this mean I can assume that even a custom written new for the object may not be invoked if I chose to write?
是的.考虑到即使在链表中,容器也不会分配您类型的实例,而是分配包含该类型子对象的模板结构.对于一个包含至少两个指针(两个链接)和您类型的子对象的复杂类型的链表.实际分配的类型是那个node,而不是你的类型.
Yes. Consider that even in linked lists, the container will not allocate an instance of your type, but rather a templated structure that contains a subobject of the type. For a linked list that will be some complex type containing at least two pointers (both links) and a subobject of your type. The actual type that is allocated is that node, not your type.
此外,列表使用 new 和 delete 也是有意义的,因为我们不需要连续的内存保证.
Also it makes sense for a list to use a new and delete as we don't need the continuous memory guarantee.
可以,但不会new
/delete
您类型的对象.
It does, but it does not new
/delete
objects of your type.
那么,这种行为是驱动分配器行为的原因吗?
So, is this kind of behavior is what drives how allocators behave?
我不太明白这部分问题.分配器是具有标准中定义的一组约束的类,包括接口(allocate
、deallocate
...)和语义( 的含义==
是一个分配的内存可以与另一个释放,类中的任何其他状态都无关紧要).
I don't really understand this part of the question. Allocators are classes that have a set of constraints defined in the standard, that include both the interface (allocate
, deallocate
...) and semantics (the meaning of ==
is that memory allocated with one can be deallocated with the other, any other state in the class is irrelevant).
可以出于不同的原因创建分配器并将其传递给容器,包括效率(如果您只分配一种类型的对象,那么您可能能够实现比 malloc
稍微高效的小块分配器-- 或不,取决于情况).
Allocators can be created and passed onto containers for different reasons, including efficiency (if you are only allocating a type of object, then you might be able to implement small block allocators slightly more efficient than malloc
--or not, depends on the situation).
关于新位置的附注
我一直觉得有趣的是,placement new 是一个似乎有两个不同含义的术语.一方面是就地构造对象的唯一方法.但它似乎也有完全不同的含义:构造这个从自定义分配器获取内存的对象.
I have always found interesting that placement new is a term that seems to have two separate meanings. On the one side is the only way of constructing an object in-place. But it seems to also have a complete different meaning: construct this object acquiring memory from a custom allocator.
事实上placement new只有一个含义,与in-place构造无关.第一种只是第二种情况,分配器由 18.4.1.3 中定义的实现(编译器)提供,不能重载.重载分配器的特定版本除了返回参数 (void*
) 之外什么都不做,以便 new-expression 可以将它传递给构造函数并在内存(未)由调用的 placement new 版本分配.
In fact there is a single meaning of placement new that has nothing to do with constructing in-place. The first is just a case of the second, where the allocator is provided by the implementation (compiler) as defined in 18.4.1.3 and cannot be overloaded. That particular version of the overloaded allocator does absolutely nothing but return the argument (void*
) so that the new-expression can pass it into the constructor and construct the object on the memory (not) allocated by the placement new version that was called.
相关文章