user2386276
user2386276

Reputation: 548

C++ exceptions: out_of_range_error from Programming Principles

I have a couple of questions concerning C++ exceptions. For reference, I am learning C++ through Bjarne Stroustrup's "Programming Principles and Practice using C++".

My first questions I think is simple: around page 147, we are talking about exceptions dealing with referencing an index outside of the range of a vector. So his try catch block is

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 error\n"
        return 1;
    } catch(...){
        cerr<<"Exception: something went wrong\n";
        return 2;
    }
}

So my question is what is out_of_range_error ?! Early on in the book he mentions the use of a header file to use so new people need not concern themselves with nuances. That file is located here but out_of_range_error is no where there. Just the standard out_of_range exception you can check for normally (after importing stdexcept). And even when I use that file (which I normally don't) the compiler (g++) tells me it expects an identifier for out_of_range_error. So is this just some typo in this mass-produced book? Or am I missing something?

My second question is on the same topic, if I don't import the file he gives, but instead just do:

#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()

then my code runs with no call to the catch block, even though I reference newVec[newVec.size()+200] in the end. It just returns a bunch of 0s with other integers randomly strewn about. I expect these are just the next bits of memory that would have been allocated for newVec, Vector is not special here, the same thing happens with arrays.

So why does C++ not do any range checking? Or does it do range checking and just not care?

If I use

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

then I get an error, but if I just want to reference, or assign to, v[20] I get no problems. Why is this?

Is this common in C++? Do you often need extra code to FORCE C++ to notice array bounds? This seems very hazardous, coming from a java background. Java would immediately alert you to any indexing errors, but C++ seems content to let you carry on with incorrect logic.

Thanks so much for any responses, sorry for a long-winded attempt at asking this question.

Upvotes: 1

Views: 311

Answers (2)

Vlad from Moscow
Vlad from Moscow

Reputation: 310980

Relative to your first question then I am sure that out_of_range_error is a typo. There should be out_of_range(See section 19.4 of the book for additional information).

As for the second question then operator [] for vectors does not throw the exception std::out_of_range it simulates the bahaviour of arrays. So there is simply undefined behaviour. If you want that there would be a check of the range then you have to use member function at

By the way if the book has errate at the site then you should look through it.

Upvotes: 2

T.C.
T.C.

Reputation: 137315

One of the most important principles motivating the design of C++ and its standard library is "you don't pay for what you don't need".

Properly written code shouldn't be accessing array (or vector) out of bounds, therefore they don't need bounds checking, and therefore they shouldn't be forced to pay for it. Bounds checking can easily double the cost of an array access. Similar designs can be seen throughout the C++ standard library - for example, std::lock_guard vs. std::unique_lock, std::condition_variable vs. std::condition_variable_any. In each case the latter class adds extra functionality at extra cost, so users who don't need the extra functionality could simply use the more lightweight version.

If you do need bounds checking, then std::vector provides the member function at() for this purpose.

Upvotes: 1

Related Questions