Meh*_*dad 14 c++ memory-management allocator c++11
我对某些事感到困惑.假设我有一个任意的C++分配器 - 比方说,像这样:
template<class T>
struct my_allocator
{
template<class Other>
struct rebind { typedef my_allocator<Other> other; };
// [other members here]
};
Run Code Online (Sandbox Code Playgroud)
现在考虑以下代码(请阅读评论):
typedef my_allocator<int> Alloc;
Alloc alloc = get_my_allocator(); // assume this works properly
long *const p = Alloc::rebind<long>::other(alloc).allocate(1, NULL);
// Notice that the rebound allocator for 'long' is now destroyed
// Can a NEW rebound allocator for 'long' deallocate the memory from the old one?
Alloc::rebind<long>::other(alloc).deallocate(p, 1);
// i.e., does the 'int' allocator 'alloc' keep alive the 'long' memory pool too?
Run Code Online (Sandbox Code Playgroud)
在什么时候可以释放后备存储池?
或者,换句话说:哪个分配器共享哪个内存池的所有权?
我总是假设 - 没有太多的想法 - 相同值类型的分配器共享其自己的内存池的所有权,但现在我想到他们也可能共享所有反弹分配器后面的内存池的所有权,即使他们管理完全不同的类型.
反弹类型的分配器必须"保持"彼此的内存池,直到它们全部被销毁?
如果C++ 03和C++ 11的答案不同,请解释它们和它们之间的区别.
How*_*ant 11
反弹类型的分配器必须"保持"彼此的内存池,直到它们全部被销毁?
简短的回答是肯定的,尽管有一点需要注意.答案很长......
C++ 11(和C++ 14)说[allocator.requirements]一个my_allocator<long>
从a构造的my_allocator<int>
必须能够删除从中分配的内存my_allocator<int>
.这在Allocator需求表中表示为:
X a(b);
Run Code Online (Sandbox Code Playgroud)
后续条件:
Y(a) == b and a == X(b)
Run Code Online (Sandbox Code Playgroud)
如您所知,operator ==用于表示:两个相等的分配器可以释放彼此分配的指针.表格文档b
也是一个类型的对象,Y
其中X
和Y
是与rebind
上面显示的相关的分配器.
现在这一点并不能解决你的确切问题,因为在你的问题中my_allocator<int>
从未实际分配任何东西.然而,同一个表中的另一行继续说下面关于allocator的operator ==:
a1 == a2
Run Code Online (Sandbox Code Playgroud)
后置条件:
仅当从每个分配的存储可以通过另一个分配时,才返回true.operator ==应具有自反性,对称性和 传递性,不得通过异常退出.
(重点是我自己)
传递意味着如果a1 == a2,a2 == a3,那么暗示a1 == a3.
这个细节指出了你的问题.第一个临时my_allocator<long>
副本从中复制,alloc
因此等于alloc
.
第二个临时my_allocator<long>
也被复制alloc
,因此也等于alloc
.此外,由于传递性质,两个临时性my_allocator<long>
也必须彼此相等.
这并不意味着它们都必须共享相同的内存池.但它确实意味着所有这三个分配器必须能够以某种方式释放彼此分配的指针.即你的例子是必须的.
C++ 03缺乏"传递"要求.话虽这么说,对C++ 11措辞的"传递"的加入被认为仅仅是C++ 03意图的"清理",而不是新的要求.因此,语言律师可以争论C++ 98 03中是否需要传递,但从实际的角度来看,代码更好地假设它是,因为这是意图.
实际上,C++ 98/03也包含了这种"黄鼠狼"的措辞(不再是C++ 11/14):
给定分配器类型的所有实例都必须是可互换的,并且始终相互比较.
即C++ 98/03容器被允许假设所有实例(实际上甚至是反弹实例)总是相等的.官方对"有状态"分配器的支持并没有真正开始,直到C++ 11.