Custom allocator for std::vector<char> is ignored

徘徊边缘 提交于 2019-12-30 08:15:30

问题


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.


回答1:


The GCC standard library will always rebind the supplied allocator so internally it does something like this (in C++03):

typedef Alloc::template rebind<value_type>::other _Allocator_type;

(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 is std::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 that vector stores and uses an A internally:

struct A : private std::allocator<char> {
    template<typename U>
      struct rebind {
        typedef A other;
      };

N.B. this will only work for vector, because vector doesn't strictly need to rebind the allocator (users are required to instantiate the template with allocator<value_type>, but GCC's vector rebinds anyway so that if users instantiate vector<int, std::allocator<char>> it still works.) For node-based containers such as std::set your allocator must be a template that can be rebound, because the container needs to allocate its internal node types, not the value_type, so it needs Alloc::rebind<internal_node_type>::other to be valid.




回答2:


vector will rebind the allocator. As you bring it into scope from std::allocator, A::rebind<T>::other will simply be std::allocator<T>. So everything works fine.



来源:https://stackoverflow.com/questions/15224988/custom-allocator-for-stdvectorchar-is-ignored

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!