C++ 标准特性:array & forward_list
一、array(STL array 容器)—— C++11
1.1 概述
std::array是 C++11 标准中新增的序列容器,它封装了固定大小的 C 风格数组。
| 特性 | 说明 |
|---|
| 头文件 | <array> |
| 大小 | 编译期确定,不可动态改变 |
| 底层 | 封装 C 风格数组 |
| 优势 | 比原生数组更安全,支持迭代器和 STL 算法 |
与vector的区别 | vector大小可变,array大小固定,array性能更接近原生数组 |
1.2 示例代码
#include<iostream>#include<array>// array容器usingnamespacestd;intmain(){std::array<int,5>arr{};// 初始化arr容器for(inti=1;i<arr.size();i++){arr.at(i)=i;}// 通过get()重载函数输出指定位置元素值cout<<"输出结果为"<<get<4>(arr)<<endl;return0;}
![]()
1.3 代码解析
array<int,5>arr{};// 创建 int 类型、大小为 5 的 array,初始值为 0arr.at(i)=i;// 带越界检查的访问(越界时抛 std::out_of_range)arr[i]=i;// 另一种访问方式(不检查越界,性能更高)get<4>(arr);// 编译期索引访问,索引越界会在编译时报错
| 访问方式 | 检查时机 | 安全性 |
|---|
arr[i] | 无检查 | ⚠️ 越界未定义行为 |
arr.at(i) | 运行时检查 | ✅ 越界抛异常 |
get<N>(arr) | 编译期检查 | ✅✅ 索引越界编译失败 |
1.4 常用成员函数速查
| 函数 | 功能 |
|---|
size() | 返回元素个数 |
at(i) | 带越界检查的元素访问 |
operator[i] | 不带越界检查的访问 |
front() | 返回第一个元素 |
back() | 返回最后一个元素 |
data() | 返回指向底层数组的指针 |
fill(x) | 将所有元素填充为 x |
swap(other) | 交换两个 array 的内容 |
二、forward_list(前向链表)—— C++11
2.1 概述
std::forward_list是 C++11 新增的容器,底层实现采用单向链表。
| 对比 | forward_list | list |
|---|
| 链表类型 | 单向链表 | 双向链表 |
| 方向 | 只能向前遍历 | 可向前/向后遍历 |
| 内存开销 | 每个节点只存一个指针 | 每个节点存两个指针(next + prev) |
| 插入/删除位置 | 只能在指定位置之后插入 | 可在指定位置之前或之后插入 |
| 适用场景 | 节省内存、只需单向遍历 | 需要双向遍历和灵活插入 |
forward_list: 节点 → 节点 → 节点 → end (只有 next 指针) list: 节点 ⇄ 节点 ⇄ 节点 ⇄ end (有 next 和 prev 指针)
2.2 示例代码
#include<iostream>#include<forward_list>usingnamespacestd;intmain(){forward_list<int>values{11,22,33};values.emplace_front(40);// 在头部插入 40cout<<"第一次输出结果为:"<<endl;for(autoi=values.begin();i!=values.end();i++){cout<<*i<<" ";}values.emplace_after(values.before_begin(),50);// 在头部之前插入 50cout<<"\n\n第二次输出结果为:"<<endl;for(autoi=values.begin();i!=values.end();i++){cout<<*i<<" ";}values.reverse();// 反转链表cout<<"\n\nreverse后输出结果为:"<<endl;for(autoi=values.begin();i!=values.end();i++){cout<<*i<<" ";}return0;}
![]()
2.3 执行过程分析
| 步骤 | 操作 | 链表状态 |
|---|
| 初始 | {11, 22, 33} | 11 → 22 → 33 |
emplace_front(40) | 头部插入 40 | 40 → 11 → 22 → 33 |
emplace_after(before_begin(), 50) | 在"头部之前"插入 50 | 50 → 40 → 11 → 22 → 33 |
reverse() | 反转链表 | 33 → 22 → 11 → 40 → 50 |
before_begin()返回一个指向第一个元素之前的迭代器。因为单向链表只能向后看,要操作头部位置,需要这个"头前"迭代器。
2.4 常用成员函数速查
| 函数 | 功能 |
|---|
emplace_front(args...) | 在头部原地构造元素 |
push_front(x) | 在头部插入元素 |
pop_front() | 移除头部元素 |
emplace_after(it, args...) | 在指定位置之后原地构造 |
insert_after(it, x) | 在指定位置之后插入 |
erase_after(it) | 删除指定位置之后的元素 |
before_begin() | 返回头前迭代器(用于操作第一个元素之前的位置) |
reverse() | 反转链表 |
empty()/clear() | 判空 / 清空 |
sort()/merge() | 排序 / 合并有序链表 |
三、array vs forward_list 对比
| 特性 | array | forward_list |
|---|
| 头文件 | <array> | <forward_list> |
| 底层结构 | 静态数组 | 单向链表 |
| 大小 | 编译期固定 | 动态增减 |
| 随机访问 | ✅ O(1) | ❌ |
| 遍历方向 | 双向(通过索引) | 单向(向前) |
| 插入/删除复杂度 | ❌ 不支持 | O(1)(指定位置之后) |
| 内存连续性 | ✅ 连续 | ❌ 非连续 |
| 适用场景 | 固定大小、需要随机访问 | 频繁插入删除、内存敏感 |