我正在编写一个分配器集合,目的是在非常高性能的环境中使用它们,因此需要一点限制使用(由编译器而非运行时错误介导)。我一直在阅读有状态分配器的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
为相同Allocator
类型的两个实例返回true
时,可以保证分配有a
的内存可以与b
解除分配。对于这个分配器来说,这似乎从来都不是真的。该标准还规定,当复制构造分配器时,如在A a(b)
中,a == b
保证返回true。
分配器要求分配器的副本必须能够释放彼此的内存,因此通常不可能将内存存储在分配器对象中。
这必须有效:
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)
因此,您需要将实际内存存储在分配器对象之外(或者只以非常有限的方式使用它,以确保对象在引用其拥有的内存时不会超出范围)。
您还将在重新绑定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);