3

I read this tutorial

std::vector beginners tutorial

and also saw this question:

similar tpoic question

Yet, when I run my simple example I did not see the excepted results, which are --> an std::out_of_range exception is NOT thrown.

Did I misunderstand here something ?

The sample code I run is the following (the code run and terminates successfully, i.e.- no exceptions thrown):

#include <iostream>
#include <vector>

using namespace std;

class MyObjNoDefualtCtor
{
public:
    MyObjNoDefualtCtor(int a) : m_a(a)
    {
        cout << "MyObjNoDefualtCtor::MyObjNoDefualtCtor - setting m_a to:" << m_a << endl;
    }

    MyObjNoDefualtCtor(const MyObjNoDefualtCtor& other) : m_a(other.m_a)
    {
        cout << "MyObjNoDefualtCtor::copy_ctor - setting m_a to:" << m_a << endl;
    }

    ~MyObjNoDefualtCtor()
    {
        cout << "MyObjNoDefualtCtor::~MyObjNoDefualtCtor - address is" << this << endl;
    }

    // just to be sure - explicitly disable the defualt ctor
    MyObjNoDefualtCtor() = delete;

    int m_a;
};


int main(int argc, char** argv)
{
    // create a vector and reserve 10 int's for it
    // NOTE: no insertion (of any type) has been made into the vector.
    vector<int> vec1;
    vec1.reserve(10);   

    // try to access the first element - due to the fact that I did not inserted NOT even a single 
    // element to the vector, I would except here an exception to be thrown.
    size_t index = 0;
    cout << "vec1[" << index << "]:" << vec1[index] << endl;

    // now try to access the last element - here as well: due to the fact that I did not inserted NOT even a single 
    // element to the vector, I would excpet here an excpetion to be thrown.
    index = 9;
    cout << "vec1[" << index << "]:" << vec1[index] << endl;

    // same thing goes for user defined type (MyObjNoDefualtCtor) as well
    vector<MyObjNoDefualtCtor> vec2;
    vec2.reserve(10);   

    // try to access the first element -  due to the fact that I did not inserted NOT even a single 
    // element to the vector, I would except here an exception to be thrown.
    index = 0;
    cout << "vec2[" << index << "]:" << vec2[index].m_a << endl;

    // now try to access the last element - here as well: due to the fact that I did not inserted NOT even a single 
    // element to the vector, I would except here an exception to be thrown.
    index = 9;
    cout << "vec2[" << index << "]:" << vec2[index].m_a << endl;

    return 0;   
}

Notes:

The sample code is compiled with -std=c++11 option.

Compiler version is g++ 5.4 (on my Ubuntu 16.04 machine).

Thanks,

Guy.

Community
  • 1
  • 1
Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
  • 5
    In the first thing you linked: *In addition to operator [], vector defines the member function at(). This function does the same thing as the operator [], but checks the index. If the index is invalid, it will throw an object of class std::out_of_range.* – chris Jan 01 '18 at 19:42
  • [`operator[]` from `std::vector`](http://en.cppreference.com/w/cpp/container/vector/operator_at) performs no bound checking, so use it with caution and know what you're getting in to. – WhozCraig Jan 01 '18 at 19:43

2 Answers2

7

A vectors operator[] function may or may not do bounds-checking. The implementations that do have bounds-checking, typically only does it for debug-builds. GCC and its standard library doesn't.

The at function on the other hand, does have mandatory bounds-checking and will be guaranteed to throw an out_of_range exception.

What happens here is simply that you go out of bounds and have undefined behavior.

Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 2
    It's worth noting that gcc's standard library [*does have* a debug version of its containers with bounds checking and iterators tracking](https://stackoverflow.com/a/5594728/214671). – Matteo Italia Jan 01 '18 at 20:17
2

Is at() that perform the range check, not (necessarily) operator[].

Your code have udefinded behaviour.

If you want to be sure to get an exception, use

vec1.at(index)

instead of

vec1[index]
max66
  • 65,235
  • 10
  • 71
  • 111
  • You are right. Did not noticed it when I wrote the sample code. When I change it to vec2.at(index) it does throw an exception as excpected. Thanks !! – Guy Avraham Jan 01 '18 at 19:52
  • 1
    @GuyAvraham - take also in count that this difference between `at()` and `operator[]` isn't specific of `std::vector` but common characteristic of STL containers; so when you can choose between `at()` and `operator[]` (also `std::array`, `std::deque`, `std::map` and `std::unordered_map`), use the faster `operator[]` when you're sure about the correctness of index or key; otherwise use the slower `at()`. For maps, take also in count that `operator[]` create the pair if not present (maybe, in some circumstances, is exactly what do you want) were `at()` throw an exception. – max66 Jan 01 '18 at 20:22