当我研究STL时,我已经通过分配器,我在互联网上找到了很多东西,或多或少我了解他们做了什么。我看过一个自定义分配器,看看它们是如何实现的,但我的问题是它们是如何被容器使用的,让我们说到Vector中?
他们总是说矢量正在使用DEFAULT分配器。例如,空向量构造函数是:
explicit vector (const allocator& alloc = allocator());
但是vector如何使用allocator?
在场景后面的vector何时何地使用Allocator :: allocate()和Allocator :: construct()?
知道为什么需要自定义分配器,它会改变什么?
答案 0 :(得分:2)
正如@BenjaminLindley所提到的,有很多地方可以在容器内使用分配器。一个例子是push_back
,,它使用分配器特征在容器内构建其参数的副本。
标准(23.2.3)将push_back
描述为:
a.push_back(t)
附加t的副本。要求:T应为CopyInsertable到X。
稍后,术语CopyInsertable定义为:
T是CopyInsertable进入X意味着,除了T之外 将MoveInsertable移入X,以下表达式格式正确:
allocator_traits<A>::construct(a, p, t)
......可以变成:
a.construct(p, t)
...有效地使用分配器a
在位置t
构建p
的副本。
答案 1 :(得分:2)
不同的编译器使用STL的不同实现,并且由这些实现来决定它们如何使用分配器。这可能会导致一些不幸的结果。
例如,我主要使用基于ARM体系结构的嵌入式系统,有一次,我试图基于固定大小的内存块实现自己的分配器,以便与list
,{{1}一起使用}和map
(我没想到它适用于set
,因为足够大的矢量会超过块的大小)。在此过程中,我发现ARM编译器v3.1使用了STL的RogueWave实现版本,其中一些容器对Allocators的行为做出了某些假设。例如,在vector
和map
的情况下:
set
- 它假设它返回了足够大的东西而不必担心它。Allocator::max_size()
速度很慢,并尝试通过一次分配多个对象来优化它(allocate()
旨在实现此目的,但我并不期望将相同的行为应用于容器像vector
和map
那样不使用连续的内存。基本上,它不是调用set
,而是调用allocate(sizeof(T))
来获取一个内存池,然后它可以在创建新对象时在内部重新分配。这些假设几乎破坏了我在该项目中使用STL的尝试 - 我最终决定使用allocate(sizeof(T) * 20)
容器。
答案 2 :(得分:0)
关于“了解这一点,为什么需要自定义分配器,它会改变什么?”
默认值只有一个策略(可能)。