如果我想获得向量中的值,我可以使用两个选项:使用[]运算符。或者我可以使用函数.at示例来使用:
vector<int> ivec;
ivec.push_back(1);
现在我可以做两件事
int x1 = ivec[0];
int x2 = ivec.at(0); // or
我听说使用at是一个更好的选择,因为当我使用该选项时,我可以在异常中抛出这个。
有人可以解释一下吗?
答案 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
但是这需要更多时间并且对计划的影响有影响。