C++ STL 分配器与 new 运算符
根据C++ Primer第4版,第755页,有一条注释说:
现代 C++ 程序通常应该使用分配器类 来分配内存。它更安全、更灵活。
我不太明白这个说法。 到目前为止,我读过的所有材料都教导在 C++ 中使用 new 来分配内存。 书中展示了向量类如何使用分配器的示例。 但是,我无法想到其他场景。
谁能帮忙澄清一下这个说法?并给我更多的例子? 我什么时候应该使用分配器,什么时候使用new
?谢谢!
According to C++ Primer 4th edition, page 755, there is a note saying:
Modern C++ programs ordinarily ought to use the allocator class
to allocate memory. It is safer and more flexible.
I don't quite understand this statement.
So far all the materials I read teach using new
to allocate memory in C++.
An example of how vector class utilize allocator is shown in the book.
However, I cannot think of other scenarios.
Can anyone help to clarify this statement? and give me more examples?
When should I use allocator and when to use new
? Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对于一般编程,是的,您应该使用
new
和delete
。但是,如果您正在编写一个库,则不应该!
我没有你的教科书,但我想它是在编写库代码的背景下讨论分配器。
图书馆的用户可能希望准确控制从哪里分配什么。如果库的所有分配都经过
new
和delete
,用户将无法进行细粒度的控制。所有 STL 容器都采用可选的分配器模板参数。然后容器将使用该分配器来满足其内部内存需求。默认情况下,如果省略分配器,它将使用
std::allocator
,它使用
new
和delete
(具体来说,::operator new(size_t)
和::operator delete (void*)
)。这样,该容器的用户可以根据需要控制内存的分配位置。
实现与 STL 一起使用的自定义分配器的示例和说明:使用 STL 的自定义池分配器提高性能
< em>附注:分配器的 STL 方法在很多方面都不是最佳的。我建议阅读走向更好的分配器模型 对其中一些问题的讨论。
2019 年编辑:自从编写此答案以来,C++ 的情况已经有所改善。 支持有状态分配器 在 C++11 中,该支持在 C++17 中得到了改进。一些参与“迈向更好的分配器模型”的人参与了这些更改(例如:N2387),这样很好(:
For general programming, yes you should use
new
anddelete
.However, if you are writing a library, you should not!
I don't have your textbook, but I imagine it is discussing allocators in the context of writing library code.
Users of a library may want control over exactly what gets allocated from where. If all of the library's allocations went through
new
anddelete
, the user would have no way to have that fine-grained level of control.All STL containers take an optional allocator template argument. The container will then use that allocator for its internal memory needs. By default, if you omit the allocator, it will use
std::allocator
which usesnew
anddelete
(specifically,::operator new(size_t)
and::operator delete(void*)
).This way, the user of that container can control where memory gets allocated from if they desire.
Example of implementing a custom allocator for use with STL, and explanation: Improving Performance with Custom Pool Allocators for STL
Side Note: The STL approach to allocators is non-optimal in several ways. I recommend reading Towards a Better Allocator Model for a discussion of some of those issues.
Edit in 2019: The situation in C++ has improved since this answer was written. Stateful allocators are supported in C++11, and that support was improved in C++17. Some of the people involved in the "Towards a Better Allocator Model" were involved in those changes (eg: N2387), so that's nice (:
两者并不矛盾。分配器是 STL 库的容器适配器使用的 PolicyPattern 或 StrategyPattern,用于分配与对象一起使用的内存块。
这些分配器经常通过允许来优化内存分配
* 一次分配的元素范围,然后使用新的放置进行初始化
* 根据块大小从辅助的、专门的堆中选择的项目无论如何
,最终结果将(几乎总是)是对象被分配新的(放置或默认)
另一个生动的例子是例如boost库如何实现智能指针。由于智能指针非常小(开销很小),因此分配开销可能会成为一种负担。对于实现来说,定义一个专门的分配器来进行分配是有意义的,因此可以拥有高效的 std::set<> 分配器。智能指针,std::map<..., smartpointer> 但是
(现在我几乎可以肯定,boost 实际上通过避免任何虚函数(因此 vft)来优化大多数智能指针的存储,使类成为 POD 结构,仅将原始指针作为存储;某些示例将不适用。 然后再推断其他类型的智能指针(引用智能指针、指向成员函数的指针、指向具有实例引用的成员函数的指针等))
The two are not contradictory. Allocators are a PolicyPattern or StrategyPattern used by the STL libraries' container adapters to allocate chunks of memory for use with objects.
These allocators frequently optimize memory allocation by allowing
* ranges of elements to be allocated at once, and then initialized using a placement new
* items to be selected from secondary, specialized heaps depending on blocksize
One way or another, the end result will (almost always) be that the objects are allocated with new (placement or default)
Another vivid example would be how e.g. boost library implements smartpointers. Because smartpointers are very small (with little overhead) the allocation overhead might become a burden. It would make sense for the implementation to define a specialized allocator to do the allocations, so one may have efficient std::set<> of smartpointers, std::map<..., smartpointer> etc.
(Now I'm almost sure that boost actually optimizes storage for most smartpointers by avoiding any virtuals, therefore the vft, making the class a POD structure, with only the raw pointer as storage; some of the example will not apply. But then again, extrapolate to other kinds of smartpointer (refcounting smartpointers, pointers to member functions, pointers to member functions with instance reference etc. etc.))