std::allocator_traits 能做但 std::allocator 不能的事情

🌟 std::allocator_traits 能做但 std::allocator 不能的事情

1️⃣ 适配自定义分配器

假设你要实现一个内存池 MyAllocator,而 STL 容器默认使用的是 std::allocator
如果你希望 STL 容器可以使用你的 MyAllocator,你 不能直接用 std::allocator,但可以通过 std::allocator_traits 让你的 MyAllocator 兼容 STL。

🚀 代码示例:
#include <iostream>
#include <memory>
#include <vector>template <typename T>
class MyAllocator {
public:using value_type = T;T* allocate(std::size_t n) {std::cout << "Allocating " << n << " objects\n";return static_cast<T*>(::operator new(n * sizeof(T)));}void deallocate(T* p, std::size_t) {std::cout << "Deallocating objects\n";::operator delete(p);}
};int main() {std::vector<int, MyAllocator<int>> vec;  // 使用自定义分配器vec.push_back(10);  // std::allocator_traits 让 vec 兼容 MyAllocatorvec.push_back(20);
}

std::allocator_traits 使 std::vector 兼容 MyAllocator,而 std::allocator 无法做到这一点


2️⃣ rebind 机制:不同类型对象之间的分配

std::allocator 时代,如果你有一个 Allocator<int>,但你想用它来分配 double,你需要手动定义 rebind

template <typename T>
struct MyAllocator {using value_type = T;template <typename U>struct rebind { using other = MyAllocator<U>; };
};

问题:

  • std::allocator<int> 不能直接用于 std::allocator<double>
  • 你必须手动实现 rebind,增加了额外的代码和复杂度。

解决方案:std::allocator_traits 自动提供 rebind

template <typename T>
class MyAllocator {
public:using value_type = T;T* allocate(std::size_t n) { return static_cast<T*>(::operator new(n * sizeof(T))); }void deallocate(T* p, std::size_t) { ::operator delete(p); }
};int main() {using Alloc = MyAllocator<int>;using ReboundAlloc = std::allocator_traits<Alloc>::rebind_alloc<double>; // 绑定到doubleReboundAlloc alloc; double* p = alloc.allocate(5);  // 现在可以分配 double 了!alloc.deallocate(p, 5);
}

std::allocator_traits 自动提供 rebind,避免手写 rebind 逻辑!


3️⃣ constructdestroy 适配自定义指针

std::allocator 时代,construct() 直接调用 new,但是如果你有一个 自定义指针(比如智能指针),你就会发现 std::allocator 无法直接适配。

问题:

  • std::allocator::construct() 只能用于普通指针 T*,不支持 std::unique_ptr<T>std::shared_ptr<T>
  • std::allocator 不支持使用 std::shared_ptr 作为 pointer 类型

解决方案:使用 std::allocator_traits 适配智能指针

#include <iostream>
#include <memory>template <typename T>
struct SmartAllocator {using value_type = T;using pointer = std::unique_ptr<T>; // 使用 unique_ptr 而不是裸指针T* allocate(std::size_t n) {return static_cast<T*>(::operator new(n * sizeof(T)));}void deallocate(T* p, std::size_t) {::operator delete(p);}
};int main() {SmartAllocator<int> alloc;using AllocTraits = std::allocator_traits<SmartAllocator<int>>;int* p = AllocTraits::allocate(alloc, 1);AllocTraits::construct(alloc, p, 42);std::cout << "Constructed value: " << *p << std::endl;AllocTraits::destroy(alloc, p);AllocTraits::deallocate(alloc, p, 1);
}

std::allocator_traits 使得 SmartAllocator 可以支持 unique_ptr,而 std::allocator 无法支持!


4️⃣ 适配 constexpr 分配器

在现代 C++ 中,某些分配器需要支持 constexpr,而 std::allocator 不能被 constexpr 调用。但 std::allocator_traits 可以提供 constexpr 支持

template <typename T>
struct ConstexprAllocator {using value_type = T;constexpr T* allocate(std::size_t n) {return new T[n];}constexpr void deallocate(T* p, std::size_t) {delete[] p;}
};constexpr int test() {ConstexprAllocator<int> alloc;using AllocTraits = std::allocator_traits<ConstexprAllocator<int>>;int* p = AllocTraits::allocate(alloc, 1);AllocTraits::construct(alloc, p, 42);int val = *p;AllocTraits::destroy(alloc, p);AllocTraits::deallocate(alloc, p, 1);return val;
}static_assert(test() == 42, "Test failed");

std::allocator_traits 使得 ConstexprAllocator 可以支持 constexpr,而 std::allocator 无法支持!


🎯 总结:std::allocator_traits 相比 std::allocator 的优越性

特性std::allocatorstd::allocator_traits
适配自定义 Allocator❌ 不支持✅ 适配 MyAllocator
支持 rebind 机制❌ 需要手写 rebind✅ 自动提供 rebind
支持智能指针❌ 不支持✅ 可以适配 unique_ptr
适配 constexpr❌ 不能 constexpr✅ 支持 constexpr
统一 STL 分配接口❌ STL 不能通用vectormap 都能用

🚀 什么时候必须用 std::allocator_traits

  1. 你在实现自定义 Allocator,并想让 STL 容器使用它。
  2. 你需要在 Allocator 中使用 unique_ptrshared_ptr
  3. 你想要 Allocator 适用于不同类型的对象(使用 rebind)。
  4. 你希望 Allocatorconstexpr 计算时可以工作。

🔥 结论

虽然 std::allocator 仍然在某些简单场景下可用,但现代 C++ 开发 几乎所有 STL 容器 都依赖 std::allocator_traits,而 std::allocator 已经不再直接使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/72298.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT——c++界面编程库

非界面编程 QT编译的时候&#xff0c;依赖于 .pro 配置文件&#xff1a; SOURCES: 所有需要参与编译的 .cpp 源文件 HEADERS:所有需要参与编译的.h 头文件 QT&#xff1a;所有需要参与编译的 QT函数库 .pro文件一旦修改&#xff0c;注意需要键盘按 ctrls 才能加载最新的配置文…

基于专利合作地址匹配的数据构建区域协同矩阵

文章目录 地区地址提取完成的处理代码 在专利合作申请表中&#xff0c;有多家公司合作申请。在专利权人地址中&#xff0c; 有多个公司的地址信息。故想利用这里多个地址。想用这里的地址来代表区域之间的专利合作情况代表区域之间的协同、协作情况。 下图是专利合作表的一部分…

汽车小助手智能体

汽车小助手&#xff1a;智能驱动汽车服务新体验 链接&#xff1a;文心智能体平台AgentBuilder | 想象即现实 文心智能体平台AgentBuilder&#xff0c;是百度推出的基于文心大模型的智能体平台&#xff0c;支持广大开发者根据自身行业领域、应用场景&#xff0c;选取不同类型的…

各种传参形式

一、QueryString 前端请求&#xff1a;http://localhost:8080/test/user/find?id26&namezhangsan 后端接收&#xff1a; 1.参数接收&#xff1a; RequestMapping("/find") public void find(String id,String name){... }2.对象接收&#xff1a; RequestMa…

【vue-echarts】——03.配置项---tooltip

文章目录 一、tooltip提示框组件二、显示结果一、tooltip提示框组件 提示框组件,用于配置鼠标滑过或点击图表时的显示框 代码如下 Demo3View.vue <template><div class="about">

VSCode轻松调试运行.Net 8.0 Web API项目

1.背景 我一直都是用VS来开发.NetCore项目的&#xff0c;用的比较顺手&#xff0c;也习惯了。看其他技术文章有介绍VS Code更轻量&#xff0c;更方便。所以我专门花时间来使用VS Code&#xff0c;看看它是如何调试代码、如何运行.Net 8.0 WebAPI项目。这篇文章是一个记录的过程…

P8720 [蓝桥杯 2020 省 B2] 平面切分--set、pair

P8720 [蓝桥杯 2020 省 B2] 平面切分--set、pair 题目 分析一、pair1.1pair与vector的区别1.2 两者使用场景两者组合使用 二、set2.1核心特点2.2set的基本操作2.3 set vs unordered_set示例&#xff1a;统计唯一单词数代码 题目 分析 大佬写的很明白&#xff0c;看这儿 我讲讲…

游戏引擎学习第128天

开始 然而&#xff0c;我们仍然有一些工作要做&#xff0c;渲染部分并没有完全完成。虽然现在已经能够运行游戏&#xff0c;而且帧率已经可以接受&#xff0c;但仍然有一些东西需要进一步完善。正在使用调试构建编译版本&#xff0c;虽然调试版本的性能不如优化版本&#xff0…

多元数据直观表示(R语言)

一、实验目的&#xff1a; 通过上机试验&#xff0c;掌握R语言实施数据预处理及简单统计分析中的一些基本运算技巧与分析方法&#xff0c;进一步加深对R语言简单统计分析与图形展示的理解。 数据&#xff1a; 链接: https://pan.baidu.com/s/1kMdUWXuGCfZC06lklO5iXA 提取码: …

第8天:面向对象编程入门 - 类与对象

第8天&#xff1a;面向对象编程入门 - 类与对象 一、&#x1f4da; 今日学习目标 &#x1f3af; 掌握类与对象的定义与使用&#x1f527; 理解封装、继承、多态三大特性&#x1f4a1; 完成银行账户管理系统实战&#x1f6e0;️ 学会构造函数与析构函数的编写 二、⚙️ 核心知…

Hadoop之02:MapReduce编程模型

MapReduce编程模型 理解MapReduce编程模型独立完成一个MapReduce程序并运行成功了解MapReduce工程流程掌握并描述出shuffle全过程&#xff08;面试&#xff09;独立编写课堂及作业中的MR程序理解并解决数据倾斜 1. MapReduce编程模型 Hadoop架构图 Hadoop由HDFS分布式存储、M…

2.7 大模型RAG内容安全合规检查-大模型ACP模拟题-真题

单选题 在RAG应用中&#xff0c;输入内容合规检查的正确顺序是&#xff1f; A. 先处理模型生成&#xff0c;后检查用户输入 B. 先检查用户输入&#xff0c;后处理模型生成 ✅ C. 仅检查用户输入 D. 仅检查模型输出 解析&#xff1a;合规流程应优先过滤用户输入风险&#xff0…

mapbox基础,使用geojson加载heatmap热力图层

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️heatmap热力图层样式二、🍀使用geojs…

Deepseek Api Function Calling解析(tools、tool_calls)Deepseek函数调用流程图、Python代码示例

文章目录 Function Calling介绍**核心原理**1. **动态扩展模型能力**2. **JSON结构化交互** **实现步骤**&#xff08;以支持Function Calling的模型为例&#xff09;1. **定义可用函数**2. **模型匹配与生成**3. **开发者执行函数**4. **结果反馈给模型** **DeepSeek R1的当前…

在2023idea中如何创建SpringBoot

目录 一.下载和安装 Maven 1.前往 https://maven.apache.org/download.cgi 下载最新版的 Maven 程序 2.将文件解压到D:Program FilesApachemaven目录 3.新建环境变量MAVEN_HOME&#xff0c;赋值D:Program FilesApachemaven 4.编辑环境变量Path&#xff0c;追加%MAVEN_HOME…

基于YOLO11深度学习的遥感视角农田检测与分割系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分割、人工智能

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

用冒泡排序法模拟qsort函数

目录 1.前言 2.qsort函数的介绍 ​3.冒泡法回顾 4.模拟qsort---buble_sort 4.1 buble_sort格式 4.2 主函数&#xff0c;以int类型为例 4.3comp_int函数的功能设计 4.4 swap函数的功能设计 5. 总代码概览 1.前言 今天&#xff0c;小邓儿带大家用冒泡排序法来模拟一下qs…

全星研发项目管理APQP软件系统:铸造芯片集成电路产业研发体系化建设平台

全星研发项目管理APQP软件系统&#xff1a;铸造芯片集成电路产业研发体系化建设平台 在芯片集成电路行业&#xff0c;研发效率和质量直接决定了企业的核心竞争力。面对日益复杂的芯片设计、日益缩短的产品生命周期以及日益严格的质量要求&#xff0c;传统的研发管理模式已难以满…

《Python实战进阶》No 11:微服务架构设计与 Python 实现

第11集&#xff1a;微服务架构设计与 Python 实现 2025年3月3日更新了代码和微服务运行后的系统返回信息截图&#xff0c;所有代码在 python3.11.5虚拟环境下运行通过。 微服务架构通过将复杂应用拆分为独立部署的小型服务&#xff0c;显著提升了系统的可扩展性和维护性。本集…

USRP7440-通用软件无线电平台

1、产品描述 USRP7440基于第三代XILINX Zynq UltraScale RFSoC架构&#xff0c;它将射频ADC、DAC、ARM、FPGA等集成一体&#xff0c;瞬时带宽可以达到2.5GHz&#xff0c;尤其适合于射频直采应用&#xff0c;比如通信与雷达。 第一代RFSOC高达4GHz • 8x 或 16x 6.554GSPS DAC…