C++ std::string索引时s[i]运行正常但s.at(i)抛出异常的原因是什么?
问题结论
首先明确:你当前场景中[]运算符的行为在C++11及之后的标准中是明确定义的合法行为,不属于未定义行为,at()抛出异常是二者的设计规则差异导致的。
规则差异说明
C++标准对std::string的下标访问方法有明确的不同约束:
operator[](size_t pos)的规则:- 当
pos < size()时,返回对应位置字符的引用,行为合法。 - 当
pos == size()时:- 针对
const修饰的std::string实例,返回值为'\0'的常量字符引用,读操作是合法的。 - 针对非
const实例,仅允许读该位置的'\0',如果修改该位置的值会触发未定义行为。
- 针对
- 只有当
pos > size()时,才会触发未定义行为。
- 当
at(size_t pos)的规则:
只要访问位置pos >= size(),无论是什么场景,都会直接抛出std::out_of_range异常,不存在例外情况。
代码问题根因
你的循环终止条件是直接判断访问到的字符是否为'\0',处理无内嵌nul的字符串(比如示例中的"item2"s,size()为5)时:
- 用
[]访问时,i=5等于size(),合法返回'\0',循环正常终止。 - 用
at()访问时,i=5满足pos >= size()的抛异常条件,直接触发越界异常。
修复方案
调整循环条件,先判断下标是否在合法范围内,再判断字符是否为nul即可,修改后的循环代码如下:
for (const string& s : vs) { for (int i = 0; i < s.size() && s.at(i); i++) cout << s.at(i); cout << "\n"; }
这样就能避免访问到pos == size()的位置,不会触发at()的越界异常,同时保留边界检查的能力。
内容的提问来源于stack exchange,提问作者doug
相关产品推荐
相关产品推荐

