16

I noticed today that std::vector::at() is significantly slower than accessing values with square brackets []. According to the doc .at() is safer because it won't let me access values beyond the bounds of the array. However, even if I access out of bound values with at(), I'll obviously still have an error, so that's something I need to avoid no matter what.

So is there any good reason why anyone would use at() instead of []?

laurent
  • 88,262
  • 77
  • 290
  • 428
  • 1
    Do you compile with optimizations turned on? – Rafał Rawicki Aug 02 '11 at 11:30
  • Not sure, I'm using QtCreator with the default build options, and I cannot see any "optimization" flag in the doc. – laurent Aug 02 '11 at 11:33
  • 1
    Probably compiling with DEBUG is the reason for std::vector::at() to be significantly slower. – Rafał Rawicki Aug 02 '11 at 11:35
  • 2
    @Rafal: Good point - the exception code shouldn't interfere *too* much with the code flow in the case when there are no exceptions - you'd mainly pay for one extra check, and a little code bloat at the call site (perhaps hampering cache performance), but with optimizations the impact of the exception code should be fairly small. – Kerrek SB Aug 02 '11 at 11:37

6 Answers6

23

If you have reason to believe that the index is not in your control, or if the control flow is particularly complicated and you're tracing bugs, then you might want to use at() during the debug phase, but never inside loops or any situation where you know that the index is safe.

Even in other situations you should either prevalidate the index (e.g. if it's user input), or if you are just getting the value from a complicated algorithm, use assert and fix the bug if there is one. [Edit.] Or perhaps if you are writing a very complicated algorithm and you aren't sure that all your indices are always valid, you could use at() inside that algorithm and put the call into a try block -- but even here it is preferable to be offensive and use with assertions.[/]

Personally, I can't see any good reasons for at() to survive into release code. You could possibly contrive some examples where you want to use exception handling as a convenient way to direct your control flow, but any such use case would be very situational.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • +1 for Kerrek's better explanation than just one has bound check one doesn't. – RoundPi Aug 02 '11 at 12:30
  • 1
    +1 also, in debug mode some implementations will perform bounds checking when using `operator[]` too, for instance, VC++ (and probably the Dinkumware library by extension) – Praetorian Aug 02 '11 at 12:36
  • 6
    I'm not the downvoter (and don't think the answer deserves a downvote) but given that the only advantage of [] is speed, if speed is largely irrelevant in the function you're writing I prefer to use at(). The way our code is set up, we log from which module an exception was thrown, so by using at() it makes it easier/quicker to troubleshoot the silly bugs that we or QA tends to find in brand new modules and features. – Warpin Aug 03 '11 at 05:34
12

The difference between at() and the operator[] is that at() signals if the requested position is out of range by throwing an out_of_range exception.
So with the at() you can react to the error state. Using the operator[] to access the vector out of index will result in undefined behavior.

mkaes
  • 13,781
  • 10
  • 52
  • 72
4

at does range check, but operator[] does not. For example, if you pass -1 to at(), an std::out_of_range will be thrown. But if you do the same thing to operator[] it will crash or strange things will happen.

If you are absolutely sure that the index is OK or you want to do the check yourself, use operator[].

neuront
  • 9,312
  • 5
  • 42
  • 71
1

at() returns the element with index i and throws range error exception if index i is out of range . so i would suggest using at() rather than [] since it yields undefined behavior if out of range. if you want safety in your proggy use at() :).

M3taSpl0it
  • 2,967
  • 6
  • 28
  • 27
1

at() throws an out_of_range exception, which [] doesn't do.

So while [] might make your application crash immediately if you try to access something out of range, at() will enable to you to handle the error at runtime.

If this is necessary for you (often times it won't be because accessing something out of range automatically means that the semantics of your code don't work as they're supposed to) you should use at().

TravisG
  • 2,373
  • 2
  • 30
  • 47
0

Assuming your not using exceptions as some sort of signal-system, the difference is that vector::at() will ALWAYS throw an exception when you try to access an index out of bounds. vector::operator[] might either return an undefined value OR throw an access violation exception (or crash).

Viktor Sehr
  • 12,825
  • 5
  • 58
  • 90
  • `operator[]` might also format your hard disk or order pizza, I'm told. Making an inclusive list of things that can happen consequent to UB is at best impossible and at worst misleading... – Kerrek SB Aug 02 '11 at 11:55