11

我试图使用自定义分配器std::vector<char>,但我注意到std::vector不需要/使用我的分配器中的任何成员函数。这怎么可能?

#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?
}

我正在使用在线 C++11 编译器 (LiveWorkSpace) 尝试上述程序,提供 g++ 4.7.2、4.8 和 4.6.3。

基本上allocate(),deallocate()construct()destroy()没有在我的分配器中定义,但是程序编译并且所有元素都将初始化为 0。

4

2 回答 2

14

GCC 标准库将始终重新绑定提供的分配器,因此在内部它会执行以下操作(在 C++03 中):

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

(在 C++11 中它使用allocator_traits但在这种情况下结果是相同的。)

然后,该向量在内部存储该类型的对象并将其用于所有(取消)分配。

由于您尚未rebind在分配器中定义成员模板,因此您只是从基类中重新声明了成员模板,重新绑定的结果是std::allocator<value_type>而不是您自己的类型。 std::allocator当然提供所有这些功能,所以这些都是使用的功能,无论您是否在自己的类型上定义它们。

您可以通过将其添加到分配器中来修复它,using alloc::rebind;以便在内部vector存储和使用A

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

注意,这仅适用于vector,因为vector不需要重新绑定分配器(用户需要用 实例化模板allocator<value_type>,但 GCCvector无论如何都会重新绑定,这样如果用户实例化vector<int, std::allocator<char>>它仍然有效。)对于基于节点的容器,例如std::set您的分配器必须是可以反弹的模板,因为容器需要分配其内部节点类型,而不是value_type,所以需要Alloc::rebind<internal_node_type>::other有效。

于 2013-03-05T13:36:16.360 回答
7

vector将重新绑定分配器。当你把它带入范围时std::allocatorA::rebind<T>::other就简单了std::allocator<T>。所以一切正常。

于 2013-03-05T13:28:36.990 回答