14

With stl::vector:

vector<int> v(1);
v[0]=1; // No bounds checking
v.at(0)=1; // Bounds checking

Is there a way to disable bounds checking without having to rewrite all at() as []? I am using the GNU Standard C++ Library.

Edit: I changed at() to [] in the area where I suspected a bottleneck, and it significantly reduced the computation time. However, since I iterate between developing the code and running experiments with it, I would like to enable bounds checking during development and disable it when I run the experiments for real. I guess Andrew's advice is the best solution.

R Samuel Klatchko
  • 74,869
  • 16
  • 134
  • 187
matthiash
  • 3,105
  • 3
  • 23
  • 34
  • 6
    To what end? There may be a better way. – i_am_jorf Mar 05 '10 at 03:19
  • You should be able to use a regular expression to replace `at()` with `[]`, and set a breakpoint to help verify that all instances were replaced. Not that one slipping through would be a disaster, the concern is just performance, right? – Potatoswatter Mar 05 '10 at 03:46
  • 4
    Why would you want to do this? If your answer is performance, then please tell me you've profiled and found that this is your bottleneck. If that's the case, then yes, rewrite your at()s as `[]`. Otherwise, let it be. – Adam Rosenfield Mar 05 '10 at 03:47
  • @Adam: And not all the `at`s either, just the hotspots. :-P – C. K. Young Mar 05 '10 at 03:54
  • @Adam: I have profiled it with oprofile, and the program uses a lot of time in libstdc++, so I want to check whether this is due to bounds checking. I want to keep bounds checking during development, but possibly disable it when I run it for real. – matthiash Mar 05 '10 at 04:41
  • 1
    You should pinpoint the exact location of bottleneck. Maybe your code spends 80% of time in malloc() having nothing to do with bounds checking :) – Sad Developer Mar 05 '10 at 07:46

8 Answers8

27

If you really want to do it (at least for a quick and dirty profiling comparison), this will work if you have no other at()s

#define at(x) operator[](x)

And if you want to keep at() for development and use operator[] in production, just wrap it in an #ifdef.

And if you do have other at()s you can always edit your #included <vector> file.

Andrew Stein
  • 12,880
  • 5
  • 35
  • 43
  • 1
    +1 Late to the party, but bearing excellent advice. This is definitely the quick-and-dirty way to profile something. – Chris Lutz Mar 05 '10 at 07:53
15

No. The bounds-checking of std::vector::at is specified by the standard, and there is no standard-conforming C++ implementation that can deviate from that.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
6

Maybe a better solution is to use [] and use checked implementation of the standard library for debug.

Fred Larson
  • 60,987
  • 18
  • 112
  • 174
5

Based on your comment that you would like to turn on/off bounds checking, you could use a wrapper template function:

template <class T>
inline typename T::reference deref(T &cont, typename T::size_type idx)
{
#if BOUNDS_CHECK
    return cont.at(idx);
#else
    return cont[idx];
#endif
}

template <class T>
inline typename T::const_reference deref(const T &cont, typename T::size_type idx)
{
#if BOUNDS_CHECK
    return cont.at(idx);
#else
    return cont[idx];
#endif
}

You would have to modify your code to enable this, but once you had it in place you could turn bound checking on or off as you wish.

I do admit that it looks a bit ugly to use:

deref(vec, 10) = ...;
R Samuel Klatchko
  • 74,869
  • 16
  • 134
  • 187
  • This should be the accepted answer since it works well and doesn't break unrelated code like Andrew Stein's solution with the `#define`. – BullyWiiPlaza Dec 12 '18 at 15:08
4

Use at() when you always want checking. Also note that this throws an exception on error, so it is potentially recoverable. If you want the faster, unchecked, accessor, use [], but algorithms that use this should be tested thoroughly because the failure mode is more severe (undefined behavior).

A couple of approaches to development-mode bounds checking for [] when using GCC on Linux:

Some other interesting discussion: vector::at vs. vector::operator[]

Community
  • 1
  • 1
Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173
3

Not a standard way. You could turn off exceptions in your compiler. You can do this with gcc with -fno-exceptions.

You should be wary of doing this though; your libraries (including the standard libraries) might not play nicely with exceptions turned off. Check your documentation, and threads like this one on the gcc mailing list.

Matt Curtis
  • 23,168
  • 8
  • 60
  • 63
2

Derive your own vector class in your own namespace like "uncheckedvector", and override the at() of the base vector type to use the array index.

Then use "using uncheckedvector::vector" will let you override all your uses of vector everywhere. This won't work if you're using fully qualified types anywhere though.

SPWorley
  • 11,550
  • 9
  • 43
  • 63
0

If you have reasonably consistent access patterns (ie/ not random access), rather than using at() or [], one approach to avoid range checking is to use iterators, using begin(), end(), and advance() or even better, through the use of the standard algorithms.

Although this doesn't solve the underlying problem of correcting at() doing range checking some implementations of the standard library (MSVC) have checked iterators for some types of builds

Andrew Walker
  • 40,984
  • 8
  • 62
  • 84