std::array 初始化必须指定编译期确定的大小且不可动态改变,本质是带尺寸的栈上结构体;推荐用花括号初始化,未初始化元素为垃圾值,零初始化需显式写={};访问用 operator[](无检查)或 at()(抛异常);传参宜用 const 引用,不支持 resize;与 C 数组等价但比 vector 更轻量。

std::array 初始化必须指定大小且不能动态改变
你声明 std::array 时,类型和长度都得在编译期确定,比如 std::array<int></int> 合法,std::array<int n></int>(n 是变量)直接报错。它不是“运行时能变的数组”,本质是带尺寸的栈上结构体封装。
常见错误现象:error: the size of an array must be an integral constant expression——多半是用了变量当模板参数。
- 初始化推荐用花括号列表:
std::array<int> a = {1, 2, 3};</int>(C++11 起支持,注意数量要匹配) - 如果只写
std::array<int> a;</int>,元素是未初始化的(POD 类型),别默认以为是零 - 想零初始化?写成
std::array<int> a = {};</int>或std::array<int> a{};</int> - 不要试图用
new std::array<t n></t>堆分配——它没意义,std::array就是为栈语义设计的
访问元素:operator[] 和 at() 的区别很实在
operator[] 不做越界检查,快但危险;at() 会抛 std::out_of_range 异常,适合调试或不确定索引来源的场景。
使用场景:循环遍历、已知范围的计算用 [];处理用户输入、配置项索引、解析数据流时优先用 at()。
立即学习“C++免费学习笔记(深入)”;
-
a[5](越界)→ 行为未定义,可能崩溃、读垃圾值、甚至“看起来正常” -
a.at(5)→ 立刻抛异常,容易定位问题 - 性能影响:
at()多一次条件判断,但现代编译器对operator[]几乎不加额外开销 - 没有
front()/back()的安全替代——调用前仍需确认size() > 0
和 C 风格数组、vector 的关键取舍点
std::array 是零成本抽象,但不是万能替代品。它和 T[N] 几乎等价(多了 size()、data() 等接口),和 std::vector 则是完全不同的设计目标。
容易踩的坑:有人因为“vector 太重”就硬套 std::array,结果发现尺寸写死导致逻辑卡死。
- 传参时,
std::array按值传递会拷贝整个内容(比如std::array<char></char>就是 4KB 拷贝)→ 优先传 const 引用:const std::array<int>&</int> - 函数返回
std::array没问题,现代编译器基本都会 RVO,不用担心效率 - 不能隐式转成指针,但
.data()返回T*,可传给需要T*的 C 接口 - 不支持
push_back、resize等操作——这不是缺陷,是设计意图:你要的是固定尺寸,那就别指望它变
迭代器和范围 for 循环用起来很顺,但要注意生命周期
std::array 的 begin()/end() 返回普通指针(不是类对象),所以迭代器开销为零,和原生数组一致。
但正因为太轻量,容易忽略它和栈生命周期强绑定的事实。
- 范围 for 完全可用:
for (int x : a) { ... },底层就是调begin()/end() - 千万别返回局部
std::array的迭代器:auto it = local_arr.begin(); return it;→ 迭代器指向已销毁内存 -
data()和begin()在空数组时都合法,但end() - begin()才是真实长度,别靠指针减法猜尺寸 - 和算法配合没问题:
std::sort(a.begin(), a.end());,但注意它排序的是副本还是引用——传引用才能改原数组
C++11 的 std::array 真正难的不是语法,而是想清楚:这个尺寸真的、永远、在所有编译路径下都不会变吗?一旦有半点动摇,就该换 std::vector 或其他方案。











