Why is using “vector.at(x)” better than “vector[x]

2019-01-18 02:04发布

问题:

If I want to get to a value in vector I can use two options : use the [] operator. Or I might use the function .at example for using :

vector<int> ivec;
ivec.push_back(1);

Now I can do both things

int x1 = ivec[0];
int x2 = ivec.at(0); // or

I heard using at is a better option because when I use that option I can throw this one in an exception.

Can somebody please explain this?

回答1:

The difference between c[i] and c.at(i) is that at() throws std::out_of_range exception if i falls outside the range of the vector, while operator[] simply invokes undefined behavior, which means anything can happen.

Nobody says at() is better than operator[]. It just depends on circumstances. As at() performs range check, it may not be desirable always, especially when your code itself makes sure that the index can never fall outside the range. In such cases, operator[] is better.

Consider the following loop:

for(size_t i = 0 ; i < v.size(); ++i)
{
   //Should I use v[i] or v.at(i)?
}

In such a loop, operator[] is always a better choice in comparison to at() member function.

I would prefer at() when I want it throw exception in case of invalid index, so that I could do the alternative work in the catch{ ...} block. Exceptions help you separate the normal code from the exceptional/alternative code as:

try
{
   size_t i = get_index(); //I'm not sure if it returns a valid index!

   T item = v.at(i); //let it throw exception if i falls outside range

   //normal flow of code
   //...
}
catch(std::out_of_range const & e)
{
   //alternative code
}

Here you could check i yourself, to make sure that it is a valid index, and then call operator[] instead of at(), but it would mix the normal code with the alternative code using if-else block which makes it difficult to read the normal flow of code. If you see above, try-catch improves the code readability, as it really separates the normal code from the alternative code, resulting in a neat and clean code.



回答2:

The only difference between at and [] is that at performs a range check, and [] does not. If you have checked the range already or have constructed your index in such a way that it cannot get out of range, and need to access an item repeatedly, you could save a few CPU cycles by opting for [] instead of an at.

Example of a single check and multiple accesses:

size_t index = get_index(vect);
if (index < 0 || index >= vect.size()) return;
if (vect[index] > 0) {
    // ....
} else if (vect[index] > 5) {
    // ....
} else ....

Example of a case when the index is constructed to be inside limits:

for (size_t i = 0 ; i != vect.size() ; i++) {
    if (vect[i] > 42) {
        // ....
    }
}


回答3:

The other answers are entirely correct, but may give the impression that it is a good idea to use at() when writing code that you'll still be debugging, as that will cause an error to be signalled. This is the case in general, but doesn't apply for most widespread compilers -- gcc can be set to perform (fatal) range checks by putting it in debug mode and something similar can probably be done in Visual Studio.



回答4:

The vector method C++ .at check for bounds therefore when the element doesn't exist in the vector and out_of_range exception is thrown .

When using [] no check for bound is performed on the vector, therefore if the element doesn't exist no exception is thrown and the result is an undefined behavior like having random values of no exeisting elemnts in the vector.

Using [] is better than at in term of safety however this will require more time and has an impact in the perfermance of the program.