为什么很多 Allocator 函数是可选的?

Why are many Allocator functions optional?

我刚刚完成了一个关于覆盖 operator new 和 delete 的个人项目,并在此过程中了解了分配器 classes。阅读了一些在线参考资料,包括 cppreference.com,我注意到许多功能被描述为可选。

我的问题是分配器接收者,例如std::set,如果其接收的分配器仅选择性地实现函数和类型,是否有效?

如果分配器需要派生自某些具有所有函数默认实现的基class,我会理解,但分配器似乎没有继承要求。

或者是因为编译错误会提醒人们需要实现这些可选功能?

作为参考,这是我第一次尝试使用分配器作为 std::set 的第三个模板参数。我处理了一个现有的例子,所以我相信我已经实现的很多东西可能是不必要的,但我还不明白如果我将来选择将分配器与其他一些 STL 容器一起使用,如何判断是否有必要。除非,再次,期望是根据编译错误来解决...?

template <typename T>
class Allocator // Custom allocator for use by AllocSet::mAllocatedPtrs to avoid infinite recursion
{               // (because inserting an element in std::set calls ::operator new, which is overridden to add to AllocSet::mAllocatedPtrs).
    public:
        typedef T value_type;
        typedef T* pointer;
        typedef T& reference;
        typedef const T* const_pointer;
        typedef const T& const_reference;
        typedef size_t size_type;
        typedef ptrdiff_t difference_type;

        template <typename U>
        struct rebind { typedef Allocator<U> other; };

        Allocator() { }
        template <typename U> Allocator(const Allocator<U>&) { }
        virtual ~Allocator() { }

        pointer allocate(size_t numT) { return (T*)(malloc(numT * sizeof(T))); }
        void deallocate(pointer p, size_type st) { free(p); }

        size_type max_size() { return size_type(-1); }

        reference operator=(const_reference) { return *this; }
        template <typename U> reference operator=(const Allocator<U>&) { return *this; }
        template <typename U> bool operator==(const Allocator<U>&) { return true; }
        template <typename U> bool operator!=(const Allocator<U>&) { return false; }

        pointer address(reference r) { return &r; }
        const_pointer address(const_reference r) { return &r; }
};

My question is how does an allocator recipient, e.g. std::set, work if its received allocator only optionally implements functions and types?

如果你看 the allocator concecpt:

Some requirements are optional: the template std::allocator_traits supplies the default implementations for all optional requirements, and all standard library containers and other allocator-aware classes access the allocator through std::allocator_traits, not directly.

这也是为什么有这么多东西是可选的 - 大多数分配器实现实际上不需要更改它们,所以何必呢?假设您有一个新的内存重组算法的想法,为什么需要定义 pointer?


Or is the reasoning that one would be alerted to the need to implement these optional functions by a compilation error?

不,分配器的概念是well defined。它指定了您可以提供什么,以及您可以提供什么。无需依赖编译错误。

您可以在 the standard、$17.6.3.5.

中找到要求