为什么很多 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.
中找到要求
我刚刚完成了一个关于覆盖 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.
中找到要求