索引超出向量类范围时没有编译错误或运行时错误?

No compilation error or run time error when index out of range of vector class?

当我使用向量类时,我发现索引超出向量范围时没有编译错误或运行时错误。问题可以通过以下代码显示

#include <iostream>
#include <vector>

using namespace std;

int main(){

  vector<double> a(10,0.0);
  a[10]=10.0;
  cout<<"a[10]="<<a[10]<<"\n";
  cout<<"size of a is "<<a.size()<<"\n";
  return 0;
}

运行这段代码的结果是

a[10]=10
size of a is 10

没有报告错误。另外要注意的是a.size()还是returns10,虽然我可以访问a[10]成功。

我的问题是有没有办法让程序在尝试索引超出向量范围时报错?

您必须使用 vector::at(index),或者在使用 [] 运算符访问元素之前手动检查范围。

使用 [] 时不检查范围会导致未定义的行为,请参阅其定义:

/**
 *  @brief  Subscript access to the data contained in the %vector.
 *  @param n The index of the element for which data should be
 *  accessed.
 *  @return  Read-only (constant) reference to data.
 *
 *  This operator allows for easy, array-style, data access.
 *  Note that data access with this operator is unchecked and
 *  out_of_range lookups are not defined. (For checked lookups
 *  see at().)
 */

at():

...
* @throw  std::out_of_range  If @a n is an invalid index.
...

这是设计使然。为了提供最佳性能,operator[] 不检查参数的有效性。就像裸数组一样,访问向量边界外的元素会导致 undefined behaviour.

...although I can access a[10] successfully...

这是未定义行为的允许表现。同样允许您的代码抛出异常、崩溃、通过所有测试但随后当着客户的面爆炸、发动核打击等。

如果索引无效,您可以使用 std::vector::at(index) for bounds-checked access. It throws std::out_of_range

边界检查与无边界检查不一定是一个全有或全无的命题:参见How to make std::vector's operator[] compile doing bounds checking in DEBUG but not in RELEASE and tools like Valgrind

补充一下其他人所说的:

  1. 虽然可以检测到您在编译过程中提到的特定情况——这相对复杂,我不知道有任何 C++ 编译器实际这样做。

  2. 如果您使用 g++ 及其 libstdc++,您可以在 #include 指令之前添加以下内容。这将启用运行时边界检查(以及对 STL 容器的许多其他检查),即使您使用通常不检查的 [] 运算符:

    #define _GLIBCXX_DEBUG 1
    

在开发/调试期间启用#2 是个好主意。