C++异常:来自编程原理的out_of_range_error

C++ exceptions: out_of_range_error from Programming Principles

本文关键字:out of error range 异常 编程 C++      更新时间:2023-10-16

我有几个关于C++异常的问题。作为参考,我正在通过Bjarne Stroustrup的"使用C++编程原理和实践"学习C++。

我认为我的第一个问题很简单:在第147页左右,我们谈论的是处理引用向量范围之外的索引的例外情况。所以他的试跳拦截是

int main(){
    try{
        vector<int> v;
        int x;
        while(cin>>x)
            v.push_back(x);
        for(int i = 0; i<=v.size();i++)
            cout<<"v["<<i<<"] == "<<v[i]<<endl;
    } catch (out_of_range_error){
        cerr<<"Oops! Range errorn"
        return 1;
    } catch(...){
        cerr<<"Exception: something went wrongn";
        return 2;
    }
}

所以我的问题是什么是out_of_range_error?!在书的早期,他提到了使用头文件,这样新人就不必关心细微差别。该文件位于此处但是out_of_range_error不存在。只有您可以正常检查的标准out_of_range异常(在导入stdexcept之后)。即使我使用该文件(我通常不使用),编译器(g++)也会告诉我它需要out_of_range_error的标识符。那么,这只是这本大规模生产的书中的一些拼写错误吗?还是我错过了什么?

我的第二个问题是关于同一主题,如果我不导入他提供的文件,而是只导入:

#include <iostream>
#include <stdexcept>
#include <vector>
using namespace std;

/*
#include "std_lib_facilities.h"
*/
int main()
{
    try
    {
        vector<int> newVec;
        int x;
        while(cin>>x)
            newVec.push_back(x);
        for(int i = 0; i<=newVec.size()+200;i++)
            cout<<newVec[i]<<endl;
        return 0;
    }//try
    catch (out_of_range)
    {
        cerr<<"runtime error: "<<endl;
        return 1;
    }//catch
}//main()

然后我的代码运行时不调用catch块,即使我最后引用了newVec[newVec.size()+200]。它只是返回一堆0和其他随机分布的整数。我预计这些只是为newVec分配的下一个内存位,Vector在这里并不特别,数组也会发生同样的情况。

那么,为什么C++不进行任何范围检查呢?或者它做范围检查而不在乎?

如果我使用

vector<int> v(10);
v.at(20) = 100;

然后我得到一个错误,但如果我只想引用或分配给v[20],我不会有问题。为什么会这样?

这在C++中常见吗?您是否经常需要额外的代码来强制C++来注意数组边界?这似乎非常危险,来自java背景。Java会立即提醒您任何索引错误,但C++似乎满足于让您继续使用不正确的逻辑。

非常感谢您的回复,很抱歉问这个问题太长时间了。

相对于你的第一个问题,我确信out_of_range_error是一个拼写错误。应该有out_of_range(更多信息请参阅本书第19.4节)。

至于第二个问题,那么向量的operator []不会抛出异常std::out_of_range,它模拟了数组的bahaviour。因此,这只是一种未定义的行为。如果你想检查范围,那么你必须使用成员函数at

顺便说一句,如果这本书在网站上有错误,那么你应该仔细阅读

激励C++及其标准库设计的最重要原则之一是"你不需要为你不需要的东西付费"。

正确编写的代码不应该越界访问数组(或向量),因此他们不需要边界检查,因此他们也不应该被迫为此付费。边界检查可以很容易地使数组访问的成本翻倍。类似的设计可以在整个C++标准库中看到,例如,std::lock_guardstd::unique_lockstd::condition_variablestd::condition_variable_any。在每种情况下,后一个类都会以额外的成本添加额外的功能,因此不需要额外功能的用户可以简单地使用更轻量级的版本。

如果确实需要边界检查,则std::vector为此提供了成员函数at()