现代 C++ 容器深度解析及实践

一、线性容器:std::array 与 std::forward_list
1. std::array:固定大小的高效容器

在传统 C++ 中,数组与 vector 的抉择常让人纠结:数组缺乏安全检查,vector 存在动态扩容开销。C++11 引入的std::array完美平衡了两者优势:

  • 特性解析

    • 编译期确定大小,内存连续分配,访问效率与 C 数组一致;
    • 封装了迭代器、size ()、empty () 等标准接口,兼容 STL 算法;
    • 避免 vector 扩容时的重分配开销,适合已知容量的场景。
  • 代码示例

#include <array>
#include <iostream>
#include <algorithm>int main() {// 初始化与基本操作std::array<int, 4> arr = {1, 3, 2, 4};std::cout << "数组大小:" << arr.size() << std::endl;// 迭代器与算法支持std::sort(arr.begin(), arr.end());for (const auto& num : arr) {std::cout << num << " ";}// 与C接口兼容int* c_ptr = arr.data();return 0;
}

  • 使用场景
    • 存储固定长度的配置项(如哈希表桶数量);
    • 替代局部 C 数组,避免越界风险;
    • 作为函数参数传递时,避免退化为指针导致的长度丢失。
2. std::forward_list:单向链表的轻量选择

与双向链表std::list相比,std::forward_list采用单向链表实现,牺牲反向遍历能力换取更紧凑的内存布局:

  • 核心优势

    • 节点仅含 next 指针,空间利用率比 list 高约 30%;
    • 支持 O (1) 复杂度的头部插入 / 删除;
    • 无 size () 方法(需遍历计算长度),适合 “添加 - 遍历” 场景。
  • 典型应用

#include <forward_list>int main() {std::forward_list<int> flist;flist.push_front(1);flist.push_front(2);// 遍历与删除auto it = flist.begin();if (it != flist.end()) {flist.erase_after(it); // 删除头节点后的元素}// 合并链表std::forward_list<int> another = {3, 4};flist.merge(another);return 0;
}
二、无序容器:哈希表的标准化实现

传统std::map/std::set基于红黑树实现,插入与查找复杂度为 O (logN)。C++11 引入的无序容器基于哈希表,平均复杂度降至 O (1):

1. 接口与性能对比

std::unordered_map为例,与std::map的关键差异:

特性std::mapstd::unordered_map
底层结构红黑树哈希表 + 链表(解决冲突)
插入复杂度O(logN)平均 O (1),最坏 O (N)
遍历顺序按键有序无固定顺序
内存开销每个节点含左右指针哈希桶 + 链表指针
适用场景需有序遍历、范围查询高频查找、无序存储
2. 实战技巧
  • 哈希函数定制
#include <unordered_map>
#include <string>struct Person {std::string name;int age;bool operator==(const Person& other) const {return name == other.name && age == other.age;}
};// 为自定义类型特化哈希函数
namespace std {template<>struct hash<Person> {size_t operator()(const Person& p) const {return hash<string>()(p.name) ^ (hash<int>()(p.age) << 1);}};
}int main() {std::unordered_map<Person, string> person_map;return 0;
}

  • 性能优化点
    • 预分配桶数量:reserve(n)避免动态扩容导致的重哈希;
    • 减少哈希冲突:选择分布均匀的哈希函数,或使用std::unordered_mapmax_load_factor调整负载因子;
    • 避免频繁修改键值:修改键值可能导致哈希位置变化,需重新插入。
三、元组 std::tuple:多类型数据的聚合神器

传统std::pair仅能存储两个元素,std::tuple则支持任意数量、任意类型的元素组合:

1. 基础操作与解包
#include <tuple>
#include <iostream>int main() {// 创建元组auto student = std::make_tuple(95, 'A', "张三");// 访问元素(编译期索引)int score = std::get<0>(student);char grade = std::get<1>(student);// 结构化绑定(C++17特性)auto [s, g, name] = student;std::cout << "姓名:" << name << ",成绩:" << s << std::endl;// 元组合并auto new_tuple = std::tuple_cat(student, std::make_tuple(18));return 0;
}
2. 运行期索引与泛型处理

C++17 引入的std::variant配合元组,实现运行期动态索引:

#include <variant>
#include <tuple>
#include <iostream>// 运行期索引元组元素
template <size_t N, typename... T>
constexpr std::variant<T...> tuple_at(const std::tuple<T...>& tpl, size_t index) {if constexpr (N >= sizeof...(T)) {throw std::out_of_range("索引越界");}if (index == N) {return std::variant<T...>{std::in_place_index<N>, std::get<N>(tpl)};}return tuple_at<(N < sizeof...(T) - 1 ? N + 1 : 0)>(tpl, index);
}int main() {auto t = std::make_tuple(10, "hello", 3.14);size_t idx = 1;std::visit([](auto&& x) { std::cout << x << std::endl; }, tuple_at<0>(t, idx));return 0;
}
3. 实用场景
  • 函数多返回值(替代结构体或 pair 嵌套);
  • 数据库记录映射(一行数据映射为元组);
  • 泛型编程中的参数包处理(如日志函数的可变参数格式化)。
四、容器选择与性能优化
  1. 按场景选容器

    • 需有序遍历:std::map/std::set
    • 高频查找:std::unordered_map/std::unordered_set
    • 固定大小数组:std::array
    • 频繁头部插入:std::forward_list
  2. 性能优化 Tips

    • std::vector预留空间:reserve()避免多次扩容;
    • 优先使用emplace_back替代push_back+ 构造;
    • std::unordered_map,合理设置哈希函数与负载因子;
    • 元组作为函数返回值时,利用std::move避免拷贝。

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

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

相关文章

数据集|猪姿态检测PigBehaviorRecognitionDataset

数据集|猪姿态检测PigBehaviorRecognitionDataset 一、数据集介绍1.1 介绍1.2 用途1.3 数据集统计 二、样本类别介绍1. Lying&#xff08;躺卧&#xff09;2. Sleeping&#xff08;睡眠&#xff09;3. Investigating&#xff08;探索&#xff09;4. Eating&#xff08;进食&…

Vue-13-前端框架Vue之应用基础路由器的使用步骤

文章目录 1 路由和路由器2 基本切换效果2.1 App.vue(根组件)2.2 components(子组件)2.2.1 Home.vue(首页)2.2.2 News.vue(新闻)2.2.3 About.vue(关于)2.3 路由器2.3.1 router/index.ts2.3.2 main.ts2.4 效果展示2.5 程序流程3 笔记3.1 路由组件和一般组件3.1.1 Header.vue(一般…

GaussDB实例级自动备份策略:构建数据安全的“自动防护网”

GaussDB实例级自动备份策略&#xff1a;构建数据安全的“自动防护网” 在数字化转型的浪潮中&#xff0c;数据库作为企业核心数据的载体&#xff0c;其安全性与可恢复性直接关系到业务的连续性。对于分布式数据库GaussDB而言&#xff0c;实例级自动备份策略是保障数据安全的关…

推荐几本关于网络安全的书

对于网络安全从业者、相关专业学生以及对网络安全感兴趣的人士而言&#xff0c;掌握扎实的网络安全知识和技能至关重要。以下推荐的几本网络安全书籍&#xff0c;涵盖了网络安全领域的多个重要方面&#xff0c;是学习和研究网络安全的优质参考资料。 1、攻击网络协议&#xff…

工业4.0浪潮下PROFIBUS DP转ETHERNET/IP在轧钢厂的创新实践

在工业自动化4.0推动制造业向智能化升级的背景下&#xff0c;轧钢厂生产对设备互联与数据协同提出更高要求。PROFIBUS DP与ETHERNET/IP协议的特性差异&#xff0c;制约着西门子PLC与工业测距仪等设备的高效协作。通过协议转换技术实现两者互通&#xff0c;为轧钢生产线注入智能…

从0开始学习R语言--Day31--概率图模型

在探究变量之间的相关性时&#xff0c;由于并不是每次分析数据时所用的样本集都能囊括所有的情况&#xff0c;所以单纯从样本集去下判断会有武断的嫌疑&#xff1b;同样的&#xff0c;我们有时候也想要在数据样本不够全面时就能对结果有个大概的了解。 例如医生在给患者做诊断…

微信小程序进度条progress支持渐变色

微信小程序自带进度条progress支持渐变色代码 .wx-progress-inner-bar {border-radius: 8rpx !important;background: linear-gradient(90deg, #FFD26E 8%, #ED0700 100%) !important; }<view class"progress-box"><progress percent"80" back…

Linux内核网络协议栈深度解析:面向连接的INET套接字实现

深入剖析Linux内核中TCP连接管理的核心机制,揭示高效网络通信的实现奥秘。 一、源地址匹配:连接建立的第一道关卡 在TCP连接建立过程中,内核需要验证源地址是否匹配。inet_rcv_saddr_equal()函数是实现这一功能的核心,它巧妙地处理了IPv4/IPv6双栈环境: bool inet_rcv_s…

Vue 项目中 Excel 导入导出功能笔记

功能概述 该代码实现了 Vue 项目中 Excel 文件的三大核心功能&#xff1a; Excel 导入&#xff1a;上传文件并解析数据&#xff0c;刷新表格展示。模板下载&#xff1a;获取并下载标准 Excel 模板文件。数据导出&#xff1a;将表格数据按多级表头结构导出为 Excel 文件。 一…

71. 简化路径 —day94

前言&#xff1a; 作者&#xff1a;神的孩子在歌唱 一个算法小菜鸡 大家好&#xff0c;我叫智 71. 简化路径 给你一个字符串 path &#xff0c;表示指向某一文件或目录的 Unix 风格 绝对路径 &#xff08;以 / 开头&#xff09;&#xff0c;请你将其转化为 更加简洁的规范路径…

Linux系统编程 | 互斥锁

1、什么是互斥锁 如果信号量的值最多为 1&#xff0c;那实际上相当于一个共享资源在任意时刻最多只能有一个线程在访问&#xff0c;这样的逻辑被称为“互斥”。这时&#xff0c;有一种更加方便和语义更加准确的工具来满足这种逻辑&#xff0c;他就是互斥锁。 “锁”是一种非常形…

数据文件写入技术详解:从CSV到Excel的ETL流程优化

文章大纲&#xff1a; 引言&#xff1a;数据文件写入在ETL流程中的重要性 在现代数据处理中&#xff0c;ETL&#xff08;提取、转换、加载&#xff09;流程是数据分析和业务决策的核心环节&#xff0c;而数据文件写入作为ETL的最后一步&#xff0c;扮演着至关重要的角色。它不…

在Cline中使用Gemini CLI,图形化界面操作:从命令行到可视化操作的全新体验,爽炸天!

在软件开发的进程中&#xff0c;命令行工具虽功能强大&#xff0c;但对部分开发者而言&#xff0c;图形化界面的直观与便捷性有着独特魅力。此前&#xff0c;Cline 新版本集成 Gemini CLI 的消息在开发者社群引发热议&#xff0c;尤其对于偏好图形界面的开发者来说&#xff0c;…

正交视图三维重建 笔记 2d线到3d线

这种代码怎么写好&#xff0c;x1tx1 x2tx2 x1x2在一条线上tx2和tx1在一条线上输出x1 y1 ty1&#xff0c;x2 y2 ty2 线过的点 的集合 俯视图找深度 测试一下 目标 四条线变一条线 复杂度贼大跑起来贼慢 加了16000条 去重 for (const [x1, y1, x2, y2, lineId, type] of front…

【耳机】IEM 前腔 后腔 泄压孔 -> 调音纸对频响曲线的影响

一、后腔 1.曲线说明 绿色&#xff1a;无调音纸 红色&#xff1a;使用Y3 粉色&#xff1a;使用Y6 2.结论 后腔是负责微调的&#xff0c;阻尼大小和低频升降成 反比。 阻 大 -> 低频 降低 阻 小 -> 低频 升高 二、前腔 1.曲线说明 红色&#xff1a;无调音纸 黄色&am…

信息安全与网络安全---引言

仅供参考 文章目录 一、计算机安全1.1 CIA三元组1.2 影响等级1.3 计算机安全的挑战 二、OSI安全体系结构2.1 安全攻击2.2 安全服务2.3 安全机制 三、基本安全设计准则四、攻击面和攻击树&#xff08;重点&#xff09;4.1 攻击面4.2 攻击树 五、习题与答案 一、计算机安全 &…

C# VB.NET取字符串中全角字符数量和半角字符数量

C# VB.NET中Tuple轻量级数据结构和固定长度数组-CSDN博客 https://blog.csdn.net/xiaoyao961/article/details/148872196 下面提供了三种统计字符串中全角和半角字符数量的方法&#xff0c;并进行了性能对比。 性能对比&#xff08;处理 100 万次 "Hello&#xff0c;世界…

CC++公司面试题[个人总结,持续更新中]

嵌入式初级面试题 姓名: 日期: 开始时间: (答题时间60分钟,答题过程中请不要上网查询资料,不可带走答卷) 1:设float a=2,b=4,c=3;,以下C语言表达式与代数式(a+b)+c计算结果不一致的是( )[3分] A.(a+b)c/2 B. (1/2)*(a+b)c C. (a+b)c*1/2 D.c/2(a+b) 2:为了向二进制文件尾部…

Qt QGraphics简述及例程 - QGraphicsView、QGraphicsScene和QGraphicsItem

Qt QGraphics简述及例程 引言一、简单例程二、关于坐标系问题 引言 QGraphics*是Qt框架中&#xff0c;主要用于处理2D图形项的显示、交互和管理的模块&#xff0c;包括QGraphicsView、QGraphicsScene和QGraphicsItem。提供了一套高效的场景-视图架构&#xff0c;适合开发复杂的…

代码随想录打卡第一天

文章讲解&#xff1a;代码随想录 视频讲解&#xff1a;手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode&#xff1a;704. 二分查找_哔哩哔哩_bilibili class Solution { public:int search(vector<int>& nums, int target) {int left0;//左边界int…