如果我想获得向量中的一个值,我可以使用两个选项:使用 [] 运算符。或者我可以使用函数 .at 示例来使用:
vector<int> ivec;
ivec.push_back(1);
现在我可以做这两件事
int x1 = ivec[0];
int x2 = ivec.at(0); // or
我听说使用 at 是一个更好的选择,因为当我使用该选项时,我可以将其抛出异常。
有人可以解释一下吗?
c[i]
和之间的区别在于,如果超出向量的范围,则会引发异常,而c.at(i)
只是at()
调用std::out_of_range
未定义的行为,这意味着任何事情都可能发生。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
提高了代码的可读性,因为它真正将普通代码与替代代码分开,从而产生整洁干净的代码。
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) {
// ....
}
}
其他答案是完全正确的,但可能给人的印象是at()
在编写仍将调试的代码时使用它是一个好主意,因为这会导致发出错误信号。这通常是这种情况,但不适用于最广泛使用的编译器——gcc 可以设置为通过将其置于调试模式来执行(致命)范围检查,并且可能在 Visual Studio 中完成类似的操作。
.at
因此,当向量中不存在元素并out_of_range
抛出异常时,向量方法 C++会检查边界。
当[]
对向量不使用边界检查时,因此如果元素不存在,则不会引发异常,结果是未定义的行为,例如向量中没有现有元素的随机值。
使用[]
比at
安全方面要好,但这将需要更多时间,并且会影响程序的性能。