I was trying to use a custom allocator for std::vector<char>
, but I noticed that std::vector
does not need/use any of the member functions from my allocator. How is this possible?
#include <vector>
struct A : private std::allocator<char> {
typedef std::allocator<char> alloc;
using alloc::value_type;
using alloc::pointer;
using alloc::const_pointer;
using alloc::difference_type;
using alloc::size_type;
using alloc::rebind;
// member functions have been removed, since the program compiles without them
};
int main() {
std::vector<char, A> v;
v.resize(4000);
for (auto& c : v)
if (c)
return 1; // never happens in my environment
return 0; // all elements initialized to 0. How is this possible?
}
I was trying the above program with an online C++11 compiler (LiveWorkSpace), providing g++ 4.7.2, 4.8 and 4.6.3.
Basically allocate()
, deallocate()
, construct()
and destroy()
are not defined in my allocator, yet the program compiles and all the elements will be initialized to 0.
The GCC standard library will always rebind the supplied allocator so internally it does something like this (in C++03):
(In C++11 it uses
allocator_traits
but in this case the result is the same.)The vector then stores an object of that type internally and uses it for all (de)allocation.
Since you haven't defined a
rebind
member template in your allocator, you've just redeclared the one from the base class, the result of the rebinding isstd::allocator<value_type>
and not your own type.std::allocator
of course provides all those functions, so those are the ones that are used, whether or not you define them on your own type.You can fix it by adding this to your allocator intead of
using alloc::rebind;
so thatvector
stores and uses anA
internally:N.B. this will only work for
vector
, becausevector
doesn't strictly need to rebind the allocator (users are required to instantiate the template withallocator<value_type>
, but GCC'svector
rebinds anyway so that if users instantiatevector<int, std::allocator<char>>
it still works.) For node-based containers such asstd::set
your allocator must be a template that can be rebound, because the container needs to allocate its internal node types, not thevalue_type
, so it needsAlloc::rebind<internal_node_type>::other
to be valid.vector
will rebind the allocator. As you bring it into scope fromstd::allocator
,A::rebind<T>::other
will simply bestd::allocator<T>
. So everything works fine.