访问存储在vector中的对象:使用std :: vector :: at或std :: vector :: operator []?

时间:2014-05-25 15:04:28

标签: c++ vector

在访问向量元素时,使用at和方括号[]之间是否存在任何差异?

我看到同样的人更喜欢myvector.at()以上myvector[],是否有更优先的东西,比如在某些情况下表现更好,或者与其他语言相同?

3 个答案:

答案 0 :(得分:5)

主要区别在于operator[]未选中,如果您尝试访问超出向量范围的内存,将导致未定义的行为,而.at会对索引进行检查并将抛出{{ 3}}例外,如果你尝试访问内存超出范围

答案 1 :(得分:4)

std::vector::atstd::vector::operator[]之间的区别在于,如果索引无效,at将抛出std::out_of_range异常,而operator[]将导致未定义的行为索引无效。

你强烈喜欢at的唯一原因是你的算法依赖于因越界输入而抛出的异常。这似乎是一个非常罕见的用例,因为在任何索引操作之前通过认真使用size()来避免越界访问是直截了当的,因此越界访问通常只是编程错误

假设越界访问是一个错误而不是一个有效的执行路径,at vs operator[]的细分如下:


at

优点

  • 所有平台上的保证行为
  • 提供(稍微)在运行时管理错误的能力

缺点

  • 不清楚越界是运行时错误还是编程错误
  • 无法在发布版本中进行优化

operator[]

优点

  • 为bug管理提供更多空间 (例如,实现可以提供断言  它捕获了所有相关的背景和中断  进入调试器或打印调试消息)
  • 可以在发布版本中进行优化
  • 使代码的推理更容易,因为它清楚地表明越界访问是编程错误

缺点

  • 并非所有平台都保证行为
  • 如果选择了优化的实现,可能会导致安全问题或其他非常重要且难以调试的错误。

总的来说,我倾向于几乎总是使用operator[],并根据我的需要选择优化版本或调试版本。将错误转换为运行时错误很少有用。

答案 2 :(得分:0)

v.at(i)检查i是否为有效索引(即0 <= i < v.size()),如果不是则抛出异常。 v[i]不执行此类检查,只是尝试访问底层缓冲区,并且如果i无效,将(可能)发生段错误。

如果您知道索引有效,我会使用[]

*正如Mankarse所说,访问数组的边界是未定义的行为。 UB的这个特定实例经常导致段错误,但也可以做其他你不想要/不期待的事情。