Should I use std::vector::at() in my code
Asked Answered
F

6

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 []?

Fathomless answered 2/8, 2011 at 11:27 Comment(4)
Do you compile with optimizations turned on?Goodson
Not sure, I'm using QtCreator with the default build options, and I cannot see any "optimization" flag in the doc.Fathomless
Probably compiling with DEBUG is the reason for std::vector::at() to be significantly slower.Goodson
@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.Prunella
P
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.

Prunella answered 2/8, 2011 at 11:32 Comment(3)
+1 for Kerrek's better explanation than just one has bound check one doesn't.Battles
+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)Draughts
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.Indistinctive
C
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.

Cancroid answered 2/8, 2011 at 11:32 Comment(3)
operator[] would most likely return a undefined value from the vectors reserved memory.Lippizaner
The correct statement is that "accessing an out-of-bound index causes undefined behaviour".Prunella
Clarified my posting. Still the app will most likely crash.Cancroid
Z
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[].

Zea answered 2/8, 2011 at 11:34 Comment(0)
N
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() :).

Nighttime answered 2/8, 2011 at 11:33 Comment(0)
S
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().

Salute answered 2/8, 2011 at 11:34 Comment(0)
L
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).

Lippizaner answered 2/8, 2011 at 11:34 Comment(1)
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...Prunella

© 2022 - 2024 — McMap. All rights reserved.