C++ 标准特性:array & forward_list
·
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容器
using namespace std;
int main()
{
std::array<int, 5> arr{ };
// 初始化arr容器
for (int i = 1; i < arr.size(); i++) {
arr.at(i) = i;
}
// 通过get()重载函数输出指定位置元素值
cout << "输出结果为" << get<4>(arr) << endl;
return 0;
}

1.3 代码解析
array<int, 5> arr{}; // 创建 int 类型、大小为 5 的 array,初始值为 0
arr.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>
using namespace std;
int main()
{
forward_list<int> values{ 11,22,33 };
values.emplace_front(40); // 在头部插入 40
cout << "第一次输出结果为:" << endl;
for (auto i = values.begin(); i != values.end(); i++) {
cout << *i << " ";
}
values.emplace_after(values.before_begin(), 50); // 在头部之前插入 50
cout << "\n\n第二次输出结果为:" << endl;
for (auto i = values.begin(); i != values.end(); i++) {
cout << *i << " ";
}
values.reverse(); // 反转链表
cout << "\n\nreverse后输出结果为:" << endl;
for (auto i = values.begin(); i != values.end(); i++) {
cout << *i << " ";
}
return 0;
}

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)(指定位置之后) |
| 内存连续性 | ✅ 连续 | ❌ 非连续 |
| 适用场景 | 固定大小、需要随机访问 | 频繁插入删除、内存敏感 |
更多推荐
所有评论(0)