29

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

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

现在我可以做这两件事

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

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

有人可以解释一下吗?

4

4 回答 4

55

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

没有人说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提高了代码的可读性,因为它真正将普通代码与替代代码分开,从而产生整洁干净的代码。

于 2012-06-23T19:00:23.107 回答
10

at和之间的唯一区别[]at执行范围检查,[]而不执行。如果您已经检查了范围,或者已经以不会超出范围的方式构建了索引,并且需要重复访问一个项目,那么您可以通过选择[]而不是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) {
        // ....
    }
}
于 2012-06-23T19:00:40.360 回答
0

其他答案是完全正确的,但可能给人的印象是at()在编写仍将调试的代码时使用它是一个好主意,因为这会导致发出错误信号。这通常是这种情况,但不适用于最广泛使用的编译器——gcc 可以设置为通过将其置于调试模式来执行(致命)范围检查,并且可能在 Visual Studio 中完成类似的操作。

于 2012-06-24T10:50:18.083 回答
0

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

[]对向量不使用边界检查时,因此如果元素不存在,则不会引发异常,结果是未定义的行为,例如向量中没有现有元素的随机值。

使用[]at安全方面要好,但这将需要更多时间,并且会影响程序的性能。

于 2017-06-26T06:50:12.673 回答