array
std::array
是 C++11 引入的固定大小数组封装类,本质就是对原生数组 T[N]
的安全封装,提供了 STL 容器的接口支持(如迭代器、begin()
、size()
、fill()
等)。
适合在栈上存储、大小已知的固定数组,功能强于 C 风格数组,效率接近裸数组。
基本语法与使用
1
2
3
4
5
6
7
| #include <array>
std::array<int, 5> arr = {1, 2, 3, 4, 5};
arr[0] = 10;
arr.at(1) = 20;
arr.size(); // == 5
arr.fill(0); // 全部置为 0
|
底层实现原理
1
2
3
4
5
| template<typename T, std::size_t N>
struct array {
T elems[N]; // 本质就是原生数组
...
};
|
- 固定大小:
N
是模板参数,编译时决定 - 栈上分配:不像
vector
使用堆内存 - 内存连续:与
T[N]
一样,可与 C 接口兼容 - 无扩容能力:只能用于固定数量元素的场景
常用接口
接口 | 功能 |
---|
at(i) | 越界检查访问 |
operator[] | 快速访问 |
front() / back() | 首/尾元素 |
size() | 返回元素数量(编译期常量) |
fill(val) | 全部赋值为 val |
begin() / end() | STL 迭代器支持 |
data() | 返回底层 T* 指针 |
1
2
| for (int x : arr) {}
std::sort(arr.begin(), arr.end());
|
与其他容器对比
容器 | 是否定长 | 是否可扩容 | 是否连续内存 | 是否支持 STL 算法 |
---|
array | ✅ | ❌ | ✅ | ✅ |
vector | ❌ | ✅ | ✅ | ✅ |
list | ❌ | ✅ | ❌(链式) | ✅ |
C 数组 T[] | ✅ | ❌ | ✅ | ❌(无接口) |
典型场景
固定大小的缓存、结构体字段
1
2
| std::array<uint8_t, 16> uuid;
std::array<char, 128> buffer;
|
与 C 接口交互
1
2
3
| void foo(char* buf);
std::array<char, 128> buffer;
foo(buffer.data());
|
注意事项
不能 resize
1
| arr.resize(10); // 编译错误
|
不能推导长度
1
| std::array a = {1,2,3}; // 错误,必须写明长度
|
必须这样写:
1
| std::array<int, 3> a = {1, 2, 3};
|
(C++20 支持 std::to_array()
自动推导)
和 C 数组区别
特性 | T[N] | std::array<T,N> |
---|
默认初始化 | ❌ | ✅(值初始化或空) |
拷贝赋值 | ❌ | ✅ |
成员函数 | ❌ | ✅(fill , size 等) |
支持 STL 算法 | ❌ | ✅ |
传参变指针 | ✅(退化) | ❌(保持类型) |
对于原生数组 int arr[3];
,不能直接用赋值操作或拷贝构造:
1
2
3
| int arr1[3] = {1,2,3};
int arr2[3];
arr2 = arr1; // 编译错误,数组不支持赋值操作
|
但 std::array
是一个封装类,支持默认的拷贝构造和赋值运算符:
1
2
3
| std::array<int, 3> a = {1,2,3};
std::array<int, 3> b;
b = a; // 元素逐个拷贝
|
std::array
vs std::vector
使用场景选择
特性/场景 | std::array | std::vector |
---|
大小是否固定 | ✅ 固定,编译期确定大小 | ❌ 动态,可运行时调整大小 |
内存分配 | 栈上分配(或内嵌对象内存) | 堆上分配,动态管理 |
性能 | 高,连续内存,无堆开销 | 稍低,可能有扩容和堆分配开销 |
安全性 | 较高,支持 .at() 越界检查 | 较高,支持 .at() 越界检查 |
是否支持动态扩容 | ❌ 不支持 | ✅ 支持 |
适合场景 | - 元素数量固定 - 小数组或嵌套数组 - 性能敏感的栈空间操作 | - 元素数量不固定 - 需要频繁插入删除 - 容器大小动态变化 |
使用方便程度 | 简单,接口少 | 丰富,功能强大 |
迭代器稳定性 | 永远有效 | 可能失效(扩容、插入、删除) |
与 C 接口兼容性 | 高,直接可获取指针,且指针有效期稳定 | 高,但需注意扩容导致地址变化 |
示例 | std::array<int, 4> a = {1,2,3,4}; | std::vector<int> v = {1,2,3,4}; |
何时选用 std::array
- 元素数量固定且已知,编译期大小确定。
- 需要最高性能,避免堆分配和内存碎片。
- 作为类成员,方便拷贝和赋值。
- 用于小型缓存、固定格式数据(如颜色通道、坐标点)。
- 需要和 C 接口无缝兼容。
何时选用 std::vector
- 元素数量不确定或动态变化。
- 需要频繁插入、删除或调整大小。
- 容器大小大或数据量庞大,堆分配更灵活。
- 希望利用丰富的 STL 算法和适配器。
- 需要可变长度数组行为。
额外建议
- 对于性能极限场景,优先考虑
std::array
,避免堆分配。 - 不确定大小时,用
std::vector
。 - C++20 以后可用
std::span
作为 array
和 vector
共享的轻量视图,避免拷贝。
作为类成员 / 模板参数
1
2
3
| struct Packet {
std::array<uint8_t, 256> data;
};
|
或者传入函数:
1
2
3
4
| template<std::size_t N>
void print(const std::array<int, N>& arr) {
for (auto x : arr) std::cout << x << " ";
}
|