33

试图更多地了解标准库是如何实际实现的,我正在检查 Visual Studio 中的所有容器。在这里,我看到了一些奇怪的结构:

在 a 的某个基类中std::list<>找到以下 typedef

typedef typename _Alloc::template rebind<_Ty>::other _Alty;

其中“_Alloc”对应于分配器模板参数(和 _Ty 包含的类型)。我很难找到这个“关键字”的一个很好的解释。到目前为止我发现的最好的事情是它是分配器接口的一部分。尽管即使cppreference也不能很好地解释这一点。

这是template rebind<>做什么的?为什么在那个位置有必要?

4

4 回答 4

37

_Alloc模板用于获取某种类型的对象。容器可能有内部需要分配不同类型的对象。例如,当您有 a 时std::list<T, A>,分配器A旨在分配类型的对象,Tstd::list<T, A>实际上需要分配某些节点类型的对象。调用节点类型_Tystd::list<T, A>需要获取一个_Ty对象的分配器,该分配器使用 . 提供的分配机制A。使用

typename _A::template rebind<_Ty>::other

指定对应的类型。现在,这个声明中有一些语法上的烦恼:

  1. 由于rebind是 的成员模板_A并且_A是模板参数,因此rebind成为从属名称。为了表明从属名称是一个模板,它需要以 . 作为前缀template。如果没有template关键字 the<将被认为是小于运算符。
  2. 该名称other还取决于模板参数,即,它也是一个从属名称。为了表明从属名称是一种类型,typename需要关键字。
于 2013-01-03T23:18:10.217 回答
9

rebind用于为与正在实现的容器的元素类型不同的类型分配内存。取自这篇 MSDN 文章

例如,给定一个 A 类型的分配器对象 al,您可以使用以下表达式分配一个 _Other 类型的对象:

A::rebind<Other>::other(al).allocate(1, (Other *)0)

或者,您可以通过编写类型来命名它的指针类型:

A::rebind<Other>::other::pointer

于 2013-01-03T23:17:45.523 回答
4

stdc++ 代码中的示例:/usr/include/4.8/ext/new_allocator.h

rebind 被定义为分配器类的结构成员;此结构定义了一个成员other ,该成员定义为专用于不同参数类型的分配器实例(另一个成员定义了可以创建不同类型对象的分配器类)

 template<typename _Tp>
    class new_allocator
    {
    public:
      ...
      template<typename _Tp1>
        struct rebind
        { typedef new_allocator<_Tp1> other; };

使用时:

  typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;

分配器的类型被引用为

  typename _Alloc::template rebind<_Tp>::other 

现在 typedef 用于定义_Tp_alloc_type - 然后可以将其用作同一事物的较短名称。

一个示例用法是在 std::list 中,其中内部列表节点也需要它的分配器,它是从参数分配器重新定义的。

于 2017-06-01T02:55:26.200 回答
0

请检查这个http://www.cplusplus.com/reference/memory/allocator/

你会看见

rebind<...> 实际上是类分配器的成员,它是 STL 的一部分,但没有给出实现的源代码。

如您所见, rebind<...> 也是一个模板,它值得一个类型来让分配器类知道我的 rebind 成员中有什么。

所以回到你的陈述: typedef typename _Alloc::template rebind<_Ty>::other _Alty; 如果你省略了模板: typedef typename _Alloc::rebind<_Ty>::other _Alty; 你可以很容易地理解 rebind 是 _Alloc 的成员,但编译器无法理解。

鉴于 rebind 是模板的性质,需要模板 rebind<_Ty> 并将其视为整体而不是两个部分。

于 2014-05-30T09:07:42.783 回答