我正在编写一个分配器集合,目的是将它们用于非常高性能的环境中,因此需要一些限制使用(由编译器调解,而不是运行时错误)。我一直在阅读有状态分配器的C ++ 11语义以及它们如何被符合容器所使用。
我已经粘贴了一个简单的分配器,下面只包含分配器对象中的一块内存。在C ++ 03中,这是非法的。
template <typename T, unsigned N>
class internal_allocator {
private:
unsigned char storage[N];
std::size_t cursor;
public:
typedef T value_type;
internal_allocator() : cursor(0) {}
~internal_allocator() { }
template <typename U>
internal_allocator(const internal_allocator<U>& other) {
// FIXME: What are the semantics here?
}
T* allocate(std::size_t n) {
T* ret = static_cast<T*>(&storage[cursor]);
cursor += n * sizeof(T);
if (cursor > N)
throw std::bad_alloc("Out of objects");
return ret;
}
void deallocate(T*, std::size_t) {
// Noop!
}
};
在C ++ 11中,这可行吗? 复制有状态分配器意味着什么?由于目标容器为源容器中的所有元素调用复制构造函数,因此必须显式复制分配器内的内存,还是默认构造足够?
这导致了一个问题,假设绩效是最终目标,propagate_on_container_
{copy
,swap
,move
}的理智值是什么? select_on_container_copy_construction
返回什么?
我很乐意根据要求提供更多细节,因为这似乎是一个相当模糊的问题 - 至少对我而言=)
这种争论源于这样的定义:当a == b
为同一true
类型的两个实例返回Allocator
时,可以保证分配给a
的内存可以被释放与b
。对于这个分配器来说,这似乎永远不会成真。该标准还规定,当复制构造分配器时,如A a(b)
,a == b
保证返回true。
答案 0 :(得分:4)
分配器要求说分配器的副本必须能够释放彼此的内存,因此通常不可能将内存存储在分配器对象中。
这必须有效:
using IAllocChar = internal_allocator<char, 1024>;
IAllocChar::pointer p
IAllocChar a1;
{
IAllocChar a2(a1);
p = std::allocator_traits<IAllocChar>::allocate(a2, 1);
}
std::allocator_traits<IAllocChar>::deallocate(a1, p, 1)
因此,您需要将实际内存存储在allocator对象之外(或者仅以非常有限的方式使用它,以确保对象不会超出范围,而任何东西都指的是它拥有的内存)。
您还要努力重新绑定internal_allocator
,以下内容应该怎样做?
using IAllocChar = internal_allocator<char, 1024>;
using IAllocInt = std::allocator_traits<IAllocChar>::rebind_alloc<int>;
IAllocChar ac;
auto pc = ac.allocate(1); // got bored typing allocator_traits ;-)
IAllocInt ai(ac);
auto pi = ai.allocate(1);
IAllocChar(ai).deallocate(pc, 1);
IAllocInt(ac).deallocate(pi, 1);