但是我如何知道容器使用哪种分配器(如果它)
在内部从模板参数重新绑定给定的分配器?
始终提供一个Allocator<T>
到构造函数(其中T
is the value_type
容器)。容器会将其转换为Allocator<U>
是必要的地方U
是容器的一些内部数据结构。这Allocator
需要提供此类转换构造函数,例如:
template <class T> class allocator {
...
template <class U> allocator(const allocator<U>&);
另外,我读到 C++11 现在使用作用域分配器,它允许
为其包含的容器重用容器的分配器。
嗯,更准确地说,C++11 有一个分配器适配器 called scoped_allocator_adaptor
:
template <class OuterAlloc, class... InnerAllocs>
class scoped_allocator_adaptor : public OuterAlloc
{
...
};
从 C++11 开始:
类模板scoped_allocator_adaptor
是一个分配器模板
指定要使用的内存资源(外部分配器)
一个容器(与任何其他分配器一样),并且还指定一个内部
分配器资源将传递给每个元素的构造函数
容器内。该适配器是用一个外部实例化的
零个或多个内部分配器类型。如果仅用一个实例化
分配器类型,内部分配器变成scoped_allocator_adaptor
本身,因此使用相同的分配器
容器和容器内每个元素的资源,
如果元素本身是容器,则它们的每个元素
递归地。如果使用多个分配器实例化,则第一个分配器
allocator 是容器使用的外部分配器,第二个
分配器被传递给容器元素的构造函数,
并且,如果元素本身是容器,则第三个分配器是
传递给元素的元素,依此类推。如果容器是嵌套的
深度大于分配器数量,最后一个分配器
被重复使用,就像在单分配器的情况下一样,对于任何剩余的
递归。 [Note: The scoped_allocator_adaptor
是从
外部分配器类型,因此可以替换外部分配器
输入大多数表达式。 —end note ]
因此,如果您指定了一个,您只能获得范围分配器的行为scoped_allocator_adaptor
作为容器的分配器。
启用作用域分配器的容器是如何实现的
与不知道作用域容器的容器大致不同?
关键是容器现在通过一个名为的新类处理其分配器allocator_traits
而不是直接处理分配器。还有容器must use allocator_traits
对于某些操作,例如构建和销毁value_type
s 在容器中。容器must not直接与分配器交谈。
例如,分配器may提供一个名为construct
它将使用给定的参数在某个地址构造一个类型:
template <class T> class Allocator {
...
template<class U, class... Args>
void construct(U* p, Args&&... args);
};
如果分配器不提供该成员,allocator_traits
将提供默认实现。无论如何,容器must构建所有value_type
正在使用这个construct
功能,但通过使用它allocator_traits
,并且不使用allocator
直接地:
allocator_traits<allocator_type>::construct(the_allocator, *ugly details*);
The scoped_allocator_adaptor
提供定制construct
函数其中allocator_traits
将转发到利用uses_allocator
特征并将正确的分配器传递给value_type
构造函数。容器仍然对这些细节一无所知。容器只需要知道它必须构造value_type
使用allocator_traits construct
功能。
容器必须处理更多细节才能正确处理有状态分配器。尽管这些细节也是通过让容器不做任何假设而是通过获取所有属性和行为来处理的allocator_traits
。容器甚至不能假设pointer
is T*
。相反,这种类型是通过询问找到的allocator_traits
这是什么。
简而言之,要构建 C++11 容器,请研究allocator_traits
。然后,当您的客户使用scoped_allocator_adaptor
.