复制有状态分配器:标准库分配器语义和内部存储器

时间:2014-02-23 22:45:08

标签: c++ stl allocator

我正在编写一个分配器集合,目的是将它们用于非常高性能的环境中,因此需要一些限制使用(由编译器调解,而不是运行时错误)。我一直在阅读有状态分配器的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_ {copyswapmove}的理智值是什么? select_on_container_copy_construction返回什么?

我很乐意根据要求提供更多细节,因为这似乎是一个相当模糊的问题 - 至少对我而言=)

这种争论源于这样的定义:当a == b为同一true类型的两个实例返回Allocator时,可以保证分配给a的内存可以被释放与b。对于这个分配器来说,这似乎永远不会成真。该标准还规定,当复制构造分配器时,如A a(b)a == b保证返回true。

1 个答案:

答案 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);