当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走

Do rebound allocators get copied/moved when an allocator aware container gets copied/moved?

本文关键字:复制 分配器 移走 是否 意识 移动      更新时间:2023-10-16

这个问题与其说是个实际问题,不如说是个好奇的问题。

在C++中,许多容器都是"基于节点的"。这意味着对于存储,它们不能真正使用传递给它们的分配器,相反,它们会执行以下操作:

typedef typename A::template rebind<node>::other node_allocator_type

并可能创建一个类似或类似类型的成员:

node_allocator_type node_allocator;

创建一个可以分配节点的分配器。很好,这一切都是有道理的,但我有一个问题,如果容器真的"有分配器意识",支持有状态分配器,那么在复制/移动容器的过程中会发生什么。

节点分配器是否也被复制/移动?这在表面上是有道理的,但当我们使用复制/移动构造函数时,用户可以指定这样的新分配器,会发生什么?

list( const list& other, const Allocator& alloc );
list( list&& other, const Allocator& alloc );

在这种情况下,other的分配器没有被复制或移动,那么新构建的列表是否会得到一个全新的node_allocator和它被复制/移动的alloc

这显然是一个实现细节,但我很好奇什么是"正确的"以及典型的实现是什么。我还认识到,在C++11之前,有状态分配器并没有得到很好的支持,因此这不是一个问题。

假设复制构造分配器(甚至是有状态分配器(是一种廉价的操作;如果它们有任何相关的资源,则应该通过引用来持有它们。此外,反弹分配器可以通过复制来构建,并且这些分配器与原始分配器相比是相等的;参见Cpp17Allocator要求中的a == b

这样做的结果是,容器可以完全自由地存储AllocatorAllocator::rebind<void>Allocator::rebind<node_type>,并在分配节点、移动时构造、get_allocator()的(prvalue!(返回等时根据需要在它们之间进行复制转换。例如,通常libstdc++存储Allocator::rebind<node_type>