2013-03-05 86 views
10

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

#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。

回答

14

GCC的标准函数库可以重新绑定提供的分配器所以在内部它确实是这样的(在C++ 03):

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

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

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

由于您尚未在分配器中定义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>实例化模板,但GCC的vector无论如何会重新绑定,因此如果用户实例化vector<int, std::allocator<char>>,它仍然有效。)对于基于节点的容器如std::set您的分配器必须是可以反弹的模板,因为容器需要分配其内部节点类型,而不是value_type,因此它需要Alloc::rebind<internal_node_type>::other才有效。

+1

实际上,为什么如果用户提供'std :: allocator '作为'vector '的分配器,它仍然可以工作?得到编译器错误是否更有意义? – 2013-03-05 13:40:01

+1

我不确定这是否令人满意,但始终如此。对于其他容器,它更有意义:如果用户说'std :: map ,std :: allocator >>'尽管可以接受它从技术上来说,分配器必须是'std :: allocator >' – 2013-03-05 13:42:56

+5

@AndyProwl - 分配器实际上应该是模板模板参数,但模板模板参数在当时不存在STL(注意:** STL **,不是**标准库**)被设计,所以'rebind'被创建。 – 2013-03-05 13:48:54

7

vector将重新绑定分配器。当您将它从std::allocator范围内调出时,A::rebind<T>::other将仅为std::allocator<T>。所以一切正常。

相关问题