C++ 抛出“std::out_of_range”实例后调用终止

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29061925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 21:08:58  来源:igfitidea点击:

terminate called after throwing an instance of 'std::out_of_range'

c++

提问by santosh

I'm a absolute beginner for programming. I got this error while building up the following code.

我是编程的绝对初学者。我在构建以下代码时遇到此错误。

error: terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check: __n (which is 8) >= this->size() (which is 8) Aborted (core dumped)


#include<iostream>
#include<vector>
#include<string>
#include<iomanip>
using namespace std;
int main()
{
    cout<<"\n Welcome to space travel calculation program";

    string cPlanet, name;
    double weight, speed, tTime, nWeight;
    int num;
    vector<string> planet;
    vector<int> distance;
    vector<double> sGravity;

    planet.push_back("Mercury");
    distance.push_back(36);
    sGravity.push_back(0.27);

    planet.push_back("Venus");
    distance.push_back(67);
    sGravity.push_back(0.86);

    planet.push_back("Earth");
    distance.push_back(93);
    sGravity.push_back(1.00);

    planet.push_back("Mars");
    distance.push_back(141);
    sGravity.push_back(0.37);

    planet.push_back("Jupiter");
    distance.push_back(483);
    sGravity.push_back(2.64);

    planet.push_back("Saturn");
    distance.push_back(886);
    sGravity.push_back(1.17);

    planet.push_back("Uranus");
    distance.push_back(1782);
    sGravity.push_back(0.92);

    planet.push_back("Neptune");
    distance.push_back(2793);
    sGravity.push_back(1.44);
    num=planet.size();

    cout<<"\n Please tell me your name: ";
    getline(cin,name);


    cout<<"\n Please choose which planet you want to travel to from the following list:"
        <<"\n 1.Mercury"
        <<"\n 2.Venus"
        <<"\n 3.Earth"
        <<"\n 4.Mars"
        <<"\n 5.Jupiter"
        <<"\n 6.Saturn"
        <<"\n 7.Uranus"
        <<"\n 8.Neptune       :";
    getline(cin,cPlanet);

    cout<<"\n What is your weight on Earth?";
    cin>>weight;

    cout<<"\n At what speed do you wish to travel? :";
    cin>>speed;

    if(cPlanet==planet.at(num))
    {
        tTime=(distance.at(num))/speed;
        nWeight=weight*sGravity.at(num);

        cout<<"\n Your Name: "<<name
            <<"\n Weight On Earth: "<<weight
            <<"\n Planet you wish to visit: "<<cPlanet
            <<"\n The speed you will be travelling at: "<<speed
            <<"\n Total time it will take to reach "<<planet.at(num)<<": "<<tTime
            <<"\n Your weight on "<<planet.at(num)<<": "<<nWeight;
    }

    return 0;
}

回答by Wintermute

Array and vector indices in C++ run from 0 to size - 1. Thus when you say

C++ 中的数组和向量索引从 0 到大小 - 1。因此,当你说

num=planet.size();

and later

然后

if(cPlanet==planet.at(num))

you are trying to access one past the endof the vector planet. The atmember function then throws an exception of type std::out_of_rangethat is never caught, and your program terminates because of that.

您正在尝试访问超过vector末尾的一个planet。然后,at成员函数抛出一个std::out_of_range永远不会被捕获的异常类型,您的程序因此而终止。

It looks as though you wanted to find the vector index corresponding to a planet name; you could do that with std::findand std::distanceas follows:

看起来好像您想找到与行星名称对应的矢量索引;您可以使用std::find和 执行std::distance以下操作:

num = std::distance(planet.begin(), std::find(planet.begin(), planet.end(), cPlanet));

this will return planet.size()if cPlanetis not found. However, it would probably be nicer to implement the whole thing with a std::map.

planet.size()如果cPlanet未找到,这将返回。但是,使用std::map.

回答by Christian Hackl

Here's a simpler program to reproduce the behaviour:

这是一个更简单的程序来重现行为:

#include <vector>

int main()
{
    std::vector<int> v;
    v.push_back(123); // v has 1 element  [0 to 0]
    v.push_back(456); // v has 2 elements [0 to 1]
    v.push_back(789); // v has 3 elements [0 to 2]
    int x1 = v.at(0); // 123
    int x2 = v.at(1); // 456
    int x3 = v.at(2); // 789
    int x4 = v.at(3); // exception
}

The atmember function throws an exception if you try to access a non-existing element.

at,如果你试图访问一个不存在的元素成员函数抛出异常。

While that principally sounds like a good thing, it turns out to be pretty useless in practice. Using an illegal vector index is almost surely a programming error, and exceptions should not be thrown for programming errors.

虽然这听起来是件好事,但在实践中却毫无用处。使用非法向量索引几乎肯定是一个编程错误,并且不应因编程错误而抛出异常

You could catchthe std::out_of_rangeexception to "recover" from the error or "handle" it, but seriously, what could you possibly do at such a low level of program logic?

你可以catchstd::out_of_range例外“恢复”从错误或“处理”,但严重的是,有什么你可以做的可能在程序逻辑的如此低的水平?

For std::vector, prefer the []operator. In your case:

对于std::vector,更喜欢[]运算符。在你的情况下:

tTime = distance[num] / speed;

[]is like at, but takes an entirely different stance on programming errors; atis like "if you should ever call me with an illegal index, I'll throw an exception so that we can somehow carry on, shall we?", whereas with the []operator the behaviour is undefinedfor illegal vector indices. This means a C++ implementation is allowed to just terminate the program without any chance of accidentally catching an exception and "continuing somehow". It depends on how you invoke the compiler and generally requires you to examine your compiler's configuration options (for example those for VC++or those for GCC).

[]就像at,但对编程错误采取完全不同的立场;at就像“如果你用非法索引给我打电话,我会抛出一个异常,这样我们就可以以某种方式继续,对吗?” ,而对于[]操作符,非法向量索引的行为是未定义的。这意味着允许 C++ 实现只是终止程序,而不会意外捕获异常并“以某种方式继续”。这取决于您如何调用编译器,并且通常要求您检查编译器的配置选项(例如那些用于 VC++用于 GCC 的配置)。

Terminating as quickly as possible is the right thing to do when you find out that your own code is wrong. Do not get used to at's behaviour.

当您发现自己的代码错误时,尽快终止是正确的做法。不习惯at的行为。