为什么在C ++中使用“vector.at(x)”比“vector [x]”更好?

时间:2012-06-23 18:57:27

标签: c++ exception vector

如果我想获得向量中的值,我可以使用两个选项:使用[]运算符。或者我可以使用函数.at示例来使用:

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

现在我可以做两件事

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

我听说使用at是一个更好的选择,因为当我使用该选项时,我可以在异常中抛出这个。

有人可以解释一下吗?

4 个答案:

答案 0 :(得分:54)

c[i]c.at(i)之间的区别在于,如果std::out_of_range超出了向量的范围,则at()会引发i异常,而operator[]只是调用未定义的行为,这意味着任何事情都可能发生。

没有人说at()operator[]好。这取决于具体情况。由于at()执行范围检查,因此可能并不总是这样,特别是当您的代码本身确保索引永远不会超出范围时。在这种情况下,operator[]会更好。

考虑以下循环:

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

在这样的循环中,与operator[]成员函数相比,at()始终是更好的选择。

如果我希望它在索引无效的情况下抛出异常,我希望at(),以便我可以在catch{ ...}块中执行替代工作。 例外可帮助您将普通代码与例外/替代代码分开为

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
}

在这里,您可以自己检查i,以确保它是有效索引,然后拨打operator[]而不是at(),但它会将正常代码与替代方案混合使用if-else块的代码,这使得很难读取正常的代码流。如果你看到上面的内容,try-catch提高了代码的可读性,因为它真正将正常代码与替代代码分开,从而产生了干净利落的代码。

答案 1 :(得分:10)

at[]之间的唯一区别是at执行范围检查,[]没有。如果您已经检查了范围或已经构建了索引,使其无法超出范围,并且需要重复访问项目,则可以通过选择[]而不是选项来节省一些CPU周期at

单次检查和多次访问的示例:

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

将索引构造为内部限制的情况示例:

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

答案 2 :(得分:0)

其他答案完全正确,但可能会给人留下这样的印象:在编写您仍在调试的代码时使用at()是个好主意,因为这会导致发出错误信号。一般情况下就是这种情况,但不适用于大多数广泛使用的编译器 - 可以通过putting it in debug mode将gcc设置为执行(致命)范围检查,并且可以在Visual Studio中完成类似的操作。

答案 3 :(得分:0)

向量方法C ++ .at检查边界因此当向量中不存在该元素并且抛出out_of_range异常时。

当使用[]时,不对向量执行绑定检查,因此如果该元素不存在则不会抛出异常,结果是未定义的行为,例如在向量中没有任何存在的元素的随机值

在安全方面使用[]优于at但是这需要更多时间并且对计划的影响有影响。