std::array本身不会抛出std::out_of_range,仅at()方法会抛该异常;operator[]不检查边界,越界为未定义行为;捕获需用try-catch包裹at()调用。

std::array 本身**不会抛出 std::out_of_range
这是最关键的前置事实——如果你在用 std::array::at() 并看到 std::out_of_range,那异常确实来自它;但若用的是 operator[],则根本不会抛异常,越界访问是未定义行为(UB),不保证崩溃,也不保证报错。
std::array::at() 是唯一会抛 std::out_of_range 的成员函数
std::array 只有 at() 方法做边界检查并抛 std::out_of_range;operator[] 完全不检查,和 C 风格数组一样裸奔。
- 正确捕获方式:
try { int x = arr.at(10); // 假设 arr 是 std::array<int> } catch (const std::out_of_range& e) { std::cerr </int> - 注意:必须捕获
const std::out_of_range&,不是std::exception或其他基类(虽然也能捕获,但会丢失类型精度) -
at()在 debug 和 release 下行为一致——只要越界就抛,不依赖编译器或标准库实现开关
为什么 operator[] 不抛异常?性能和契约设计使然
std::array 的定位是栈上固定大小容器,目标是零开销抽象。加运行时检查违背这一原则,所以 operator[] 故意不检查。
- 越界读可能返回垃圾值,写可能覆盖相邻变量(比如破坏下一个局部变量或返回地址)
- 某些编译器(如 GCC 启用
-fsanitize=undefined)能在运行时检测并中止,但这属于 UBSan 行为,不是标准规定 - 别指望
operator[]抛异常来“兜底”——它不会,也不能依赖它来发现逻辑错误
替代方案:静态断言 + 调试断言更实用
比起依赖 at() 捕获异常,多数场景下更推荐编译期或调试期拦截:
- 用
static_assert确保索引是编译期常量且合法:constexpr size_t idx = 3; static_assert(idx
- 调试时用
assert快速暴露问题:#include <cassert> assert(i </cassert>
- 若需统一边界检查又不想写 try/catch,可封装一层安全访问函数,内部调用
at()并处理异常或返回std::optional
真正容易被忽略的点是:很多人以为 std::array 像 std::vector 一样,operator[] 在 debug 模式下会检查——它不会。这种假设会导致线上环境突然出现难以复现的内存破坏,而不是预期的异常终止。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











