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 示例代码

cpp 复制代码
#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 代码解析

cpp 复制代码
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 示例代码

cpp 复制代码
#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)(指定位置之后)
内存连续性 ✅ 连续 ❌ 非连续
适用场景 固定大小、需要随机访问 频繁插入删除、内存敏感