Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vector::at vs. vector::operator[]

Tags:

c++

stl

stdvector

People also ask

Is [] operator faster than at?

The operator[] is 5 to 10 times faster than at(), both in release & debug builds (VS2008 x86).

Can you use [] for vectors?

Access and update element in vector using [] As, operator [] returns a reference to the element in vector, so we can change the content of vector too using operator [] i.e.

Is [] vector as fast as an array C++?

A std::vector can never be faster than an array, as it has (a pointer to the first element of) an array as one of its data members. But the difference in run-time speed is slim and absent in any non-trivial program. One reason for this myth to persist, are examples that compare raw arrays with mis-used std::vectors.

What is the difference between std :: array and std::vector?

Difference between std::vector and std::array in C++Vector is a sequential container to store elements and not index based. Array stores a fixed-size sequential collection of elements of the same type and it is index based. Vector is dynamic in nature so, size increases with insertion of elements.


I'd say the exceptions that vector::at() throws aren't really intended to be caught by the immediately surrounding code. They are mainly useful for catching bugs in your code. If you need to bounds-check at runtime because e.g. the index comes from user input, you're indeed best off with an if statement. So in summary, design your code with the intention that vector::at() will never throw an exception, so that if it does, and your program aborts, it's a sign of a bug. (just like an assert())


it forces me to wrap it with try-catch block

No it doesn't (the try/catch block can be upstream). It is useful when you want an exception to be thrown rather than your program to enter undefined behavior realm.

I agree that most out of bounds accesses to vectors are a programmer's mistake (in which case you ought to use assert to locate those mistakes more easily; most debug versions of standard libraries do this automatically for you). You do not want to use exceptions that can be swallowed upstream to report programmer mistakes: you want to be able to fix the bug.

Since it is unlikely that an out of bounds access to a vector is part of the normal program flow (in the case it is, you're right: check beforehand with size instead of letting the exception bubble up), I agree with your diagnostic: at is essentially useless.


What are advantages of using vector::at over vector::operator[] ? When should I use vector::at rather than vector::size + vector::operator[] ?

The important point here is that exceptions allow separation of the normal flow of code from the error handling logic, and a single catch block can handle problems generated from any of myriad throw sites, even if scattered deep within function calls. So, it's not that at() is necessarily easier for a single use, but that sometimes it becomes easier - and less obfuscating of normal-case logic - when you have a lot of indexing to validate.

It's also noteworthy that in some types of code, an index is being incremented in complex ways, and continually used to look up an array. In such cases, it's much easier to ensure correct checks using at().

As a real-world example, I have code that tokenises C++ into lexical elements, then other code that moves an index over the vector of tokens. Depending on what's encountered, I may wish to increment and check the next element, as in:

if (token.at(i) == Token::Keyword_Enum)
{
    ASSERT_EQ(tokens.at(++i), Token::Idn);
    if (tokens.at(++i) == Left_Brace)
        ...
    or whatever

In this kind of situation, it's very hard to check whether you've inappropriately reached the end of the input because that's very dependent on the exact tokens encountered. Explicit checking at each point of use is painful, and there's much more room for programmer error as pre/post increments, offsets at the point of use, flawed reasoning about the continued validity of some earlier test etc. kick in.


at can be clearer if you have a pointer to the vector:

return pVector->at(n);
return (*pVector)[n];
return pVector->operator[](n);

Performance aside, the first of these is the simpler and clearer code.


In debug builds, it is not guaranteed for at() to be slower than operator[]; I'd expect them to be about the same speed. The difference is that at() specifies exactly what will happen in there is a bounds error (an exception), where as in the case of operator[], it is undefined behavior — a crash in all of the systems I use (g++ and VC++), at least when the normal debugging flags are used. (Another difference is that once I'm sure of my code, I can get a substantial speed increase for operator[] by turning the debugging off. If the performance requires it — I wouldn't do it unless it were necessary.)

In practice, at() is rarely appropriate. If the context is such that you know the index may be invalid, you probably want the explicit test (e.g. to return a default value or something), and if you know that it can't be invalid, you want to abort (and if you don't know whether it can be invalid or not, I'd suggest that you specify your function's interface more precisely). There are a few exceptions, however, where the invalid index may result from parsing user data, and the error should cause an abort of the entire request (but not bring the server down); in such cases, an exception is appropriate, and at() will do that for you.