4

When I was using vector class, I found out that there is no compilation error or run time error when indexing out of range of a vector. The problem can be shown by the following code

#include <iostream>
#include <vector>

using namespace std;

int main(){

  vector<double> a(10,0.0);
  a[10]=10.0;
  cout<<"a[10]="<<a[10]<<"\n";
  cout<<"size of a is "<<a.size()<<"\n";
  return 0;
}

The result of running this code is

a[10]=10
size of a is 10

with no error reported. Another thing to notice is that a.size() still returns 10, although I can access a[10] successfully.

My question is that is there a way to let the program report an error when one tries to index out of the range of a vector?

andy90
  • 525
  • 5
  • 19

3 Answers3

8

This is by design. To offer maximum performance, operator[] does not check the argument for validity. Just like with naked arrays, accessing an element outside the bounds of a vector results in undefined behaviour.

...although I can access a[10] successfully...

This is a permissible manifestation of undefined behaviour. It is equally permissible for your code to throw an exception, to crash, to pass all your tests but then blow up in your customer's face, to launch a nuclear strike etc.

You could use std::vector::at(index) for bounds-checked access. It throws std::out_of_range if the index is not valid.

Bounds checking vs no bounds checking does not have to be an all-or-nothing proposition: see How to make std::vector's operator[] compile doing bounds checking in DEBUG but not in RELEASE and tools like Valgrind.

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • Is there a big performance impact by using `std::vector::at(index)`? – andy90 Jan 03 '15 at 12:30
  • 1
    @andy90: That depends on your compiler, platform, optimisation settings, your definition of "big", etc. The only way to know for sure is by benchmarking it under representative conditions. – NPE Jan 03 '15 at 12:33
2

You'll have to use vector::at(index), or manually check the ranges before you access the elements using the [] operator.

Not checking ranges when using [] leads to undefined behavior, see its definition:

/**
 *  @brief  Subscript access to the data contained in the %vector.
 *  @param n The index of the element for which data should be
 *  accessed.
 *  @return  Read-only (constant) reference to data.
 *
 *  This operator allows for easy, array-style, data access.
 *  Note that data access with this operator is unchecked and
 *  out_of_range lookups are not defined. (For checked lookups
 *  see at().)
 */

at():

...
* @throw  std::out_of_range  If @a n is an invalid index.
...
Maroun
  • 94,125
  • 30
  • 188
  • 241
2

To add to what others have said:

  1. While it is possible to detect the specific case you mention during compilation -- this is relatively complicated and I'm not aware of any C++ compiler actually doing this.

  2. If you're using g++ with its libstdc++ you can add the following before your #include directives. This will enable runtime bounds checking (and many other checks on STL containers) even if you use the [] operator which normally isn't checked:

    #define _GLIBCXX_DEBUG 1
    

It's a good idea to enable #2 during development / debugging.

nimrodm
  • 23,081
  • 7
  • 58
  • 59