C++STL---静态数组array
1. std::array
定义
std::array
是 C++11 标准模板库(STL)提供的一个固定大小数组容器,定义在 <array>
头文件中。
它把 C 风格的静态数组(如 int arr[5]
)封装成一个类模板,并提供 STL 容器的接口,使其能和 STL 算法无缝配合。
定义格式:
#include <array>
std::array<T, N> arr;
T
:元素类型N
:数组大小,必须是编译期常量(constexpr)
例子:
std::array<int, 5> a1; // 5个int,值未初始化
std::array<int, 5> a2 = {1,2,3}; // 前3个初始化,剩余为0
std::array<int, 5> a3{}; // 所有元素值初始化(为0)
2. std::array
优势
C 风格数组有几个明显的缺点:
- 容易退化(decay)成指针,丢失尺寸信息
void func(int arr[]) {// 这里 arr 是 int*,sizeof(arr) 不是数组大小 }
- 不支持迭代器,不能直接用 STL 算法
- 没有成员函数,需要依赖全局函数(
std::begin
,std::end
等)
std::array
保留了 C 风格数组固定大小、栈上分配的优点,同时解决了上述缺点,提供:
- 随机访问迭代器
- 成员函数接口(
size()
,empty()
,front()
,back()
,data()
等) - 支持 STL 算法
- 值语义(可以整体赋值、按值传递)
3. 特性总结
特性 | 说明 |
---|---|
固定大小 | 大小在编译期确定,不能动态增加或减少 |
连续内存 | 底层是连续内存布局,支持指针运算 |
栈上存储 | 元素存储在栈上(如果 std::array 本身在栈上) |
随机访问 | 支持下标 [] 和 at() ,时间复杂度 O(1) |
可复制 | 支持直接赋值、拷贝构造 |
可比较 | 支持 ==, !=, <, >, <=, >= 运算符(按字典序) |
STL 兼容 | 提供迭代器、begin()/end() 、rbegin()/rend() |
4. 成员类型
std::array
支持的常见类型别名:
std::array<int, 5>::value_type; // int
std::array<int, 5>::size_type; // size_t
std::array<int, 5>::reference; // int&
std::array<int, 5>::const_reference; // const int&
std::array<int, 5>::iterator; // 随机访问迭代器
std::array<int, 5>::reverse_iterator;// 反向迭代器
5. 成员函数与常用操作
5.1 构造与赋值
std::array<int, 3> a1{1, 2, 3};
std::array<int, 3> a2 = a1; // 拷贝构造
std::array<int, 3> a3;
a3 = a1; // 赋值
5.2 元素访问
std::array<int, 5> arr = {1,2,3,4,5};
int x = arr[2]; // 下标访问,无越界检查
int y = arr.at(2); // 带越界检查,抛出 std::out_of_range
int f = arr.front(); // 第一个元素
int b = arr.back(); // 最后一个元素
int* p = arr.data(); // 返回指向底层数组的指针
5.3 迭代器
for (auto it = arr.begin(); it != arr.end(); ++it) {std::cout << *it << " ";
}
// C++11 range-based for
for (int x : arr) {std::cout << x << " ";
}
// 反向迭代
for (auto it = arr.rbegin(); it != arr.rend(); ++it) {std::cout << *it << " ";
}
5.4 容量相关
std::array<int, 5> arr;
std::cout << arr.size(); // 5
std::cout << arr.max_size();// 5(固定大小)
std::cout << arr.empty(); // false(大小为0才返回true)
5.5 修改操作
arr.fill(42); // 所有元素设为42
std::array<int, 5> arr2{1,2,3,4,5};
arr.swap(arr2); // 交换两个array的内容(必须同类型同大小)
6. 与 STL 算法配合
std::array
是 STL 容器,可直接用 <algorithm>
中的算法:
#include <algorithm>
#include <iostream>
#include <array>int main() {std::array<int, 5> arr = {3,1,4,1,5};// 排序std::sort(arr.begin(), arr.end());for (int x : arr) std::cout << x << " "; // 1 1 3 4 5std::cout << "\n";// 查找auto it = std::find(arr.begin(), arr.end(), 3);if (it != arr.end()) {std::cout << "找到3在位置:" << (it - arr.begin()) << "\n";}
}
7. 与其他数组类型对比
特性 | C 风格数组 | std::array | std::vector |
---|---|---|---|
大小 | 编译期固定 | 编译期固定 | 运行期可变 |
存储位置 | 栈或静态区 | 栈(若对象在栈上) | 堆 |
赋值 | 不能直接整体赋值 | 可以整体赋值 | 可以整体赋值 |
退化 | 会退化成指针 | 不会退化 | 不会退化 |
STL 兼容 | 否(需借助 std::begin ) | 是 | 是 |
内存开销 | 零额外开销 | 零额外开销 | 有控制结构开销 |
8. 优缺点
优点
- 零额外开销:和原生数组一样高效
- 类型安全:不会隐式退化成指针
- STL 兼容:支持迭代器和 STL 算法
- 值语义:可直接赋值、按值传递
- 支持结构化绑定(C++17):
std::array<int, 3> arr{1,2,3}; auto [x, y, z] = arr; // x=1, y=2, z=3
缺点
- 大小固定:不能动态扩容
- 大小必须是编译期常量
- 存储在栈上:如果过大,可能导致栈溢出
数组选择建议
- 需要固定大小、性能敏感且在栈上分配时,优先用
std::array
- 需要动态大小时,用
std::vector
- 与 C API 交互时,用
.data()
获取底层指针 - 需要编译期常量数据容器时,
std::array
很合适(可配合constexpr
)