vector::at() 运行时检查越界并抛出异常,operator[] 不检查、行为未定义;应依数据可信度与调试需求选择:不可信输入或需防御性检查时用at(),可信索引的性能敏感循环中用[]。

vector::at() 会做越界检查,operator[] 不会
这是最核心的区别:at() 在运行时检查下标是否在 [0, size()) 范围内,越界则抛出 std::out_of_range 异常;而 operator[] 完全不检查,行为是未定义的(UB)——可能读到垃圾值、崩溃、静默出错,甚至看似正常但埋下隐患。
什么时候该用 at(),什么时候用 []
用 at() 的典型场景:
- 下标来自用户输入、文件读取、网络数据等不可信来源
- 调试阶段想快速暴露越界问题(配合异常断点)
- 逻辑上本应安全但想加一层防御性检查(如算法边界条件未完全推导清楚)
用 operator[] 的典型场景:
- 循环索引由
for (size_t i = 0; i 严格控制 - 性能敏感路径(如 inner loop),且你 100% 确保索引合法
- 已通过断言(
assert(i )做过静态保证
at() 的开销和编译器优化能力
at() 的检查无法被编译器完全优化掉,即使你在调用前刚检查过 i ,编译器通常仍会保留第二次比较(因为 at() 是函数调用,有潜在副作用)。对比之下,operator[] 是内联的,零开销。
立即学习“C++免费学习笔记(深入)”;
示例:
std::vectorv = {1, 2, 3}; size_t i = 5; if (i < v.size()) { auto x = v.at(i); // 这里仍会执行越界检查 —— 即使前面刚判断过 }
如果真要兼顾安全与性能,更合理的写法是:
if (i < v.size()) {
auto x = v[i]; // 直接用 [],信任自己的判断
} else {
throw std::out_of_range("index out of bounds");
}
数组越界检查不能只靠 at()
at() 只对 std::vector 生效,对原生数组(int arr[10])、std::array(默认也不检查)、指针运算(ptr[i])完全无效。C++ 没有全局数组边界检查机制。
真正能覆盖更多越界场景的方案包括:
- 启用 AddressSanitizer(
-fsanitize=address),可捕获原生数组、栈数组、堆内存越界读写 - 用
std::span(C++20)替代裸指针,配合operator[]时可手动加 assert 或封装安全访问 - 静态分析工具(如 clang-tidy 的
cppcoreguidelines-pro-bounds-array-to-pointer-decay)提前发现风险模式
别以为用了 at() 就高枕无忧——它只是 vector 的一道窄门,门外还有大片未设防的内存区域。









