out_of_range 字符串异常

out_of_range exception with strings

我试图理解 out_of_range 字符串中的异常

#include<iostream>
#include<exception>
using namespace std;

int main()
{
    try{
        string str = "Hello";
        str.at(100);//throws exception and get caught
        //str[100]; //this is a run time error, program crashes
    }
    catch (out_of_range &e)
    {
        cout << e.what() << endl;
    }

}

为什么数组访问字符串不会抛出任何异常和崩溃,而 .at 工作正常?

IDE:VS2013

这是因为 [] 运算符不检查任何内容,而 at() 会检查任何内容。 CppReference 说:

std::basic_string::at

Returns a reference to the character at specified location pos. Bounds checking is performed, exception of type std::out_of_range will be thrown on invalid access.

std::basic_string::运算符[]

Returns a reference to the character at specified location pos. No bounds checking is performed.

std::string::atstd::string::operator[] 的工作方式不同。

  • at(size_t) 方法检查字符串的当前大小:如果超出范围 - 将抛出异常。

  • operator[](size_t)是直接访问内存块。所以问题是在运行时。

std::string::operator[]

std::string::at

对于长度为 n 的字符串 s,您可以访问索引 0 到 n-1(含)的项目,具有 []at,具有明确定义的行为。

通过 [] 访问索引 n 处的项目 (1) 保证产生对零对象的引用, 而通过 at 访问它是 (2) 保证抛出 out_of_range 异常。

前一种行为是为了与 C 编程的预期兼容,而后一种行为是为了确保正确性。

确实,对于 0 到 n-1 范围之外的任何索引,at 方法保证会抛出 out_of_range 异常。

对于 [],您访问的索引 (3) 需要 在 0 到 [=41 的范围内=]n。这意味着使用该范围之外的索引是未定义的行为。


1) C++14 21.4.5/2 关于 basic_string::operator[]: “Returns: *(begin() + pos)如果 pos < size()。否则,returns 对类型对象的引用 charT,值为 charT(),其中修改对象会导致未定义的行为。
2)。 C++14 21.4.6/5 关于 basic_string::at:“Throwsout_of_range if pos >= size()”,其中索引类型是无符号的。
3) C++14 21.4.5/1 关于 basic_string::operator[]:“需要pos <= size。”