allocator::rebind详解

本文深入解析C++模板分配器的rebind接口,解释其为何存在,如何工作,并通过实例说明如何利用rebind接口实现不同数据类型使用相同内存分配策略的需求。了解同族分配器的概念,以及如何自定义分配器模板以适应容器需求。

rebind的本质应该这么说:给定了类型T的分配器Allocator=allocator<T>,现在想根据相同的策略得到另外一个类型U的分配器allocator<U>,那么allocator<U>=allocator<T>::Rebind<U>::other.

之所以要提供rebind接口,是因为容器只知道模板参数名Allocator,而不知其具体实现,容器只知道这样三个事情:
1、Alocator是T的分配器,但其内部实现策略是什么容器并不关心(可能是std::allocator<T>,也可能是myallocator<T>)。换句话说,容器并不知道allocator模板名。
2、类型T和类型U在逻辑上是相关的,比如在链表中,数据类型T和结点类型Node<T>是有联系的。
3、容器希望按照和T一样的策略(具体的说就是相同的allocator模板名)来分配U类型的对象。
这时rebind的作用就体现出来了,标准中规定
对一个allocator<T>,和一个类型U,必须有allotor<T>::rebind<U>::other=allocator<U>,这样,
容器就可以得到U的分配器,
也就是说,rebind的本质应该是:,
对allotor<T>::rebind<U>,T和U的分配器必须是同一个模板名。这个模板可以是std::allocator,也可以是用户自定义的分配器模板Myallocator,自然,为了使自己的分配器可以作为容器的模板参数,Myallocator中也必须定义rebind成员,且其实现必为
template<typename U>
rebind{
typedef Myallocator<U> other;
};
因此,同族的分配器指的是具有相同模板名的一组分配器。
如std::allcoator<T>和std::allcoator<U>是同族的,你可以把std::allcoator<T>::rebind<U>::other看成std::allcoator<U>。
Myallocator<T>和Myallocator<U>是同族的,你可以把Myallcoator<T>::rebind<U>::other看成Myallcoator<U>。

但allcoator<T>和Myallocator<U>就不是同族的.

Alocator 是内存分配器,STL在这个层面上进行开放是为了让用户/程序员有权选择不同的内存分配器。举例来说,Allocator_A和Allocator_B在内存分配方式上可能是不一样的,也就是说Allocator_A<int>和Allocator_B<int>所分配的内存很有可能是不一样的。

假如有一个容器类MyVector, 它用的是Allocator_A<int>内存分配器,这个容器类很有可能需要double类型的分配器,而且要求对int和double类型的内存分配策略是一样的,这时rebind的意义就体现出来了。


总之一句话,rebind实现了对不同类型使用同一种内存分配策略的要求。


转自http://bbs.youkuaiyun.com/topics/200079053

这行代码是一个典型的 C++ 模板元编程(template metaprogramming)中的类型定义,使用了 `typedef`、模板特化、嵌套类型和条件选择机制。我们来逐步解析它的含义、作用以及可能的上下文。 --- ### ✅ 回答问题: ```cpp typedef typename TChooseClass< Allocator::NeedsElementType, typename Allocator::template ForElementType<ElementType>, typename Allocator::ForAnyElementType >::Result ElementAllocatorType; ``` #### 1. **逐部分解释** - `Allocator::NeedsElementType` 这应该是一个**编译期布尔常量**(如 `true_type` 或 `false_type`),表示该分配器是否需要知道元素的具体类型(即是否依赖于 `ElementType`)。它用于在编译时决定走哪个分支。 - `TChooseClass<Condition, TypeIfTrue, TypeIfFalse>` 这是一个**类型选择元函数**(type selector),类似于 `std::conditional_t<Cond::value, A, B>`。其作用是: - 如果 `Condition` 为真,则 `TChooseClass::Result` 是 `TypeIfTrue` - 否则是 `TypeIfFalse` 它等价于现代 C++ 中的: ```cpp std::conditional_t<Allocator::NeedsElementType::value, typename Allocator::template ForElementType<ElementType>, typename Allocator::ForAnyElementType> ``` - `typename Allocator::template ForElementType<ElementType>` - 这里 `ForElementType` 是一个**模板嵌套类或别名模板**,接受元素类型 `ElementType` 作为模板参数。 - `template` 关键字告诉编译器:`ForElementType<...>` 是一个模板,避免语法歧义。 - `typename` 表示后面是一个类型(因为是在依赖上下文中)。 - `typename Allocator::ForAnyElementType` - 这是一个不需要具体元素类型的分配器类型,可能是通用版本(比如基于 `void*` 的分配器)。 - `::Result` - `TChooseClass` 的结果类型通过成员 `Result` 暴露出来,这是模板元编程中常见的手法。 - 最终结果被 `typedef` 成 `ElementAllocatorType` —— 即根据 `Allocator` 是否需要元素类型信息,在两种实现之间做选择。 --- #### 2. **整体语义** 这段代码的作用是: > 根据 `Allocator` 是否需要具体的元素类型(由 `NeedsElementType` 决定),从两个候选类型中选择合适的分配器实现: > > - 若需要元素类型 → 使用 `ForElementType<ElementType>` > - 否则 → 使用泛化的 `ForAnyElementType` 这是一种**静态多态 + 类型萃取 + 条件编译选择**的技术,常见于高性能容器库(如 Unreal Engine、STL 自定义分配器系统等)。 --- #### 3. **等价现代写法(C++11 及以后)** 如果你用标准库,可以改写为: ```cpp using ElementAllocatorType = std::conditional_t< Allocator::NeedsElementType::value, typename Allocator::template ForElementType<ElementType>, typename Allocator::ForAnyElementType >; ``` 或者如果 `NeedsElementType` 是一个 `bool` 值: ```cpp using ElementAllocatorType = std::conditional_t< Allocator::NeedsElementType, typename Allocator::template ForElementType<ElementType>, typename Allocator::ForAnyElementType >; ``` --- #### 4. **为什么会这样设计?** 这种结构允许同一个 `Allocator` 接口支持两种模式: - **类型感知分配器(type-aware)**:能对特定类型进行优化(例如对象构造/析构、对齐处理) - **类型无关分配器(type-agnostic)**:只负责内存分配释放,不关心类型 通过编译期判断,避免运行时代价,同时保持接口统一。 --- ### 示例代码(模拟实现) ```cpp #include <cstddef> #include <new> // 简单的 true_type / false_type 模拟 struct true_type { static constexpr bool value = true; }; struct false_type { static constexpr bool value = false; }; // 类型选择工具(相当于 std::conditional) template<bool Cond, typename T, typename F> struct TChooseClass { using Result = T; }; template<typename T, typename F> struct TChooseClass<false, T, F> { using Result = F; }; // 示例分配器基类 struct MyAllocator { using ForAnyElementType = int*; // 简化为指针 template<typename T> struct ForElementType { using type = T*; }; using NeedsElementType = true_type; // 需要元素类型 }; // 使用场景 template<typename Allocator, typename ElementType> struct Container { typedef typename TChooseClass< Allocator::NeedsElementType::value, typename Allocator::template ForElementType<ElementType>::type, typename Allocator::ForAnyElementType >::Result ElementAllocatorType; ElementAllocatorType ptr; }; ``` --- ### 总结 | 组件 | 含义 | |------|------| | `TChooseClass` | 编译期类型选择器(类似 `std::conditional`) | | `NeedsElementType` | 控制是否需要元素类型信息 | | `ForElementType<T>` | 类型相关的分配器实现 | | `ForAnyElementType` | 类型无关的分配器实现 | | `typename/template` | 解决依赖名称解析问题 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值