The C++11 standard (or at least, this working draft) requires that classes which implement the Allocator
concept provide copy constructors.
This made sense back when all allocators had to be stateless, but when state is allowed in an allocator class, providing a copy constructor might not be desirable. For example, if the allocator implements some kind of slab allocation system or memory pool, where it maintains an internal freelist. It seems to me that such an allocator should always be moved, never copied. Actually copying it would require allocating new storage and then completely reproducing the internal state of the original allocator, including all free memory blocks, free-lists, etc. (Or does "copying" an Allocator
simply imply returning Allocator()
, i.e. returning a new default-constructed allocator?)
Actually copying a state-ful allocator seems to be totally unnecessary because as far as I can see, in practice there's no real common use-case for copy-constructing an allocator. No Container
actually copies an allocator - C++11 containers will call Allocator::select_on_container_copy_construction
within the container copy constructor instead, which usually just returns Allocator()
. Then the container will usually just copy element by element from the other container, probably by just calling Container::insert
.
Of course an optimized container implementation might do something more complex using internal knowledge about the container structure, but still nobody is going to copy-construct other.get_allocator()
- the Container will just call other.get_allocator().select_on_container_copy_construction()
to get a default-constructed allocator.
So why do we have the requirement that an Allocator itself must be copy-constructible? Shouldn't move construction be sufficient?
Note: To be clear, this question is not a duplicate of why does allocator in c++ need a copy constructor?. That question is asking specifically about std::allocator
(which is stateless), whereas I am asking about custom allocators that implement the Allocator
concept.
Re the claim
” No
Container
actually copies an allocator
that may be so (I haven't tested), and std::string
may be regarded as a non-Container
, but still:
#include <string>
#include <iostream>
#include <memory> // std::allocator
template< class Type >
struct Alloc
: std::allocator<Type>
{
using Base = std::allocator<Type>;
template< class Other >
struct rebind
{
using other = Alloc<Other>;
};
Alloc() {}
Alloc( Alloc<Type> const& other )
: Base( other )
{ std::clog << "Alloc::<copy>\n"; }
template<class Other>
Alloc( Alloc<Other> const& other )
: Base( other )
{ std::clog << "Alloc::<generic-copy>\n"; }
};
auto main() -> int
{
using namespace std;
basic_string< char, char_traits<char>, Alloc<char> > a = "A", b = "B";
a = b;
}
Output with Visual C++:
Alloc::<copy> Alloc::<copy>
With g++ the number of allocator copy operations is higher.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With