STL 容器分配放置新

发布于 2024-10-22 02:04:31 字数 269 浏览 6 评论 0原文

我找不到这个问题的确切答案,因此在这里发帖。 当我想到向量时,它需要在连续的内存位置构建对象。这意味着向量保持分配的内存,并且必须对推入其中的对象进行就地构造(=放置新的)。这是一个有效的假设吗?另外,这是否意味着容器正在手动调用析构函数而不是调用删除?我在这里还缺少其他假设吗?这是否意味着我可以假设,如果我选择编写,即使是为该对象编写的自定义新内容也可能不会被调用?

列表使用 new 和 delete 也是有意义的,因为我们不需要连续内存保证。那么,这种行为是驱动分配器行为的原因吗?请帮忙。 谢谢

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?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

终遇你 2024-10-29 02:04:31

这意味着向量保持分配的内存,并且必须对推入其中的对象进行就地构造(=placement new)。这是一个有效的假设吗?

是的

此外,这是否意味着容器正在手动调用析构函数而不是调用删除?

是的

我这里还缺少其他假设吗?这是否意味着我可以假设,如果我选择编写,即使是为该对象自定义编写的 new 也可能不会被调用?

是的。请考虑,即使在链接列表中,容器也不会分配类型的实例,而是分配包含该类型的子对象的模板化结构。对于链表,它将是某种复杂类型,包含至少两个指针(两个链接)和您类型的子对象。分配的实际类型是节点,而不是您的类型。

列表使用 new 和 delete 也是有意义的,因为我们不需要连续内存保证。

确实如此,但它不会new/delete 您类型的对象。

那么,这种行为是驱动分配器行为的原因吗?

我不太明白问题的这一部分。分配器是在标准中定义了一组约束的类,其中包括接口(allocatedeallocate...)和语义(== 是指用一个分配的内存可以用另一个释放,类中的任何其他状态都是不相关的)。

可以出于不同的原因创建分配器并将其传递到容器上,包括效率(如果您只分配一种类型的对象,那么您可能能够实现比 malloc 稍微高效一些的小块分配器 - 或者不是,要看情况)。

关于placement new的旁注

我一直觉得有趣的是placement new这个术语似乎有两个不同的含义。一方面是就地构造对象的唯一方法。但它似乎也有一个完全不同的含义:构造这个对象,从自定义分配器获取内存

事实上,placement new只有一个含义,与in-place构造无关。第一种只是第二种情况,其中分配器由 18.4.1.3 中定义的实现(编译器)提供,并且不能重载。该特定版本的重载分配器除了返回参数 (void*) 之外什么也不做,以便 new-expression 可以将其传递到构造函数中并在构造函数上构造对象。内存(不是)由调用的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?

Yes

Also, does this mean the container is manually invoking the destructor rather than calling delete?

Yes

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?

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.

Also it makes sense for a list to use a new and delete as we don't need the continuous memory guarantee.

It does, but it does not new/delete objects of your type.

So, is this kind of behavior is what drives how allocators behave?

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).

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).

Side note on 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.

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.

南街女流氓 2024-10-29 02:04:31

你已经非常接近完全正确了。 vector(以及所有其他标准容器)进行分配的方式是使用 std::allocator 类,该类支持在特定情况下构造和析构对象地点。在内部,这使用放置新的和显式析构函数调用来设置和销毁对象。

我说“非常接近完全正确”的原因是,可以通过提供新的分配器作为模板参数代替默认分配器来自定义 STL 容器获取内存的方式。这意味着理论上应该可以让 STL 容器以不同的方式构造和析构对象,尽管默认情况下它们将使用标准放置 new。

You're very close to being perfectly correct. The way that the vector (and all the other standard containers) do their allocation is by using the std::allocator class, which has support for constructing and destructing objects at particular locations. Internally, this uses placement new and explicit destructor calls to set up and destroy objects.

The reason I say "very close to being perfectly correct" is that it's possible to customize how STL containers get their memory by providing a new allocator as a template argument in lieu of the default. This means that in theory it should be possible to have STL containers construct and destruct objects in different ways, though by default they will use the standard placement new.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文