C++ 11有状态分配器是否可以跨类型边界互换?

Sil*_*ler 11 c++ allocator c++11

我的问题基本上是跟进:

考虑到复制构造的要求,如何在C++ 11中编写有状态分配器?

基本上,尽管C++ 11标准现在允许有状态分配器,但我们仍然要求如果复制某个Allocator,则副本必须通过==运算符与原始值进行比较.这表明副本可以安全地释放由原始分配的内存,反之亦然.

因此,这样就可以禁止分配器维护独特的内部状态,例如slab-allocator或内存池等等.一种解决方案是使用shared_ptr指针实现习惯用于内部状态,以便某些原始的所有副本Allocator使用相同的底层内存池.那不算太糟糕.除了...

根据上面提到的问题,以及接受的答案,标准也似乎需要Allocator<T>具有可互操作的拷贝构造函数Allocator<U>,因此:

Allocator<T> alloc1;
Allocator<U> alloc2(alloc1);
assert(alloc1 == alloc2); // must hold true
Run Code Online (Sandbox Code Playgroud)

换句话说,无论模板参数如何,分配器类型都必须是可互操作的.这意味着如果我使用分配一些内存Allocator<T>,我必须能够使用Allocator<U>从原始构造的实例释放该内存Allocator<T>.

...这对于任何尝试编写使用某种基于大小的内存池的分配器来说都是一个显示阻塞,就像simple_segregated_storage池只返回基于某个大小的块一样sizeof(T).

但是......这是真的吗?

我意识到需要可互操作的复制构造函数,Allocator<T>::rebind因此容器的用户不需要知道say的内部细节,链接列表节点类型等.但据我所看到的,标准本身似乎并没有说什么,以便严厉作为一个要求Allocator<U>构建从Allocator<T>一定原文比较平等Allocator<T>的实例.

该标准基本上需要以下语义,其中X是类型Allocator<T>,a1和a2是X的实例,Y是类型Allocator<U>,b是实例Allocator<U>.

来自:§17.6.3.5(分配器要求)

a1 == a2 returns true only if storage allocated from each can be deallocated via the other.

operator == shall be reflexive, symmetric, and transitive, and shall not exit via an exception.

a1 != a2 : same as !(a1 == a2)

a == b : same as a == Y::rebind<T>::other(b)

a != b : same as !(a == b)

X a1(a); Shall not exit via an exception. post: a1 == a

X a(b); Shall not exit via an exception. post: Y(a) == b, a == X(b)
Run Code Online (Sandbox Code Playgroud)


所以,这样我读到这,的情况下,Allocator<T>从构造Allocator<U>是不是一定是可以互换的.该标准仅要求a == b必须等同于Y(a) == b,   不能说a == b一定是真的!

我认为对跨类型边界复制构造函数的要求使这一点令人困惑.但是,我读这个的方式,如果我有一个Allocator<T>,它必须有一个复制构造函数Allocator<U>,但这并不意味着:

Allocator<T> alloc1;
Allocator<U> alloc2(alloc1);
assert(alloc2 == alloc1); 
Run Code Online (Sandbox Code Playgroud)

换句话说,我读这个的方式,允许上面的断言失败.但我对此的理解并不自信,因为:

  1. 这个问题的公认答案另有说法,而且回答者是一个声誉为108K的人

  2. 复制构造函数要求与标准中的相等要求之间的相互作用有点令人困惑,我可能误解了这个词.

所以,我在这里是正确的吗?(顺便说一下,boost::pool_allocator假设升级开发人员关心标准合规性,实现似乎意味着我是正确的,因为这个分配器在类型边界上是不可互换的.)

How*_*ant 3

您引用的最后一行:

X a(b); 不得通过异常退出。邮政:Y(a) == b,a == X(b)

和你的结论有冲突。

using X = Allocator<T>;
using Y = Allocator<U>;
Y b;
X a(b);
assert(Y(a) == b);
assert(a == X(b));
// therefore
assert(a == b);
Run Code Online (Sandbox Code Playgroud)