索引超出向量类范围时没有编译错误或运行时错误?
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。
补充一下其他人所说的:
虽然可以检测到您在编译过程中提到的特定情况——这相对复杂,我不知道有任何 C++ 编译器实际这样做。
如果您使用 g++
及其 libstdc++
,您可以在 #include
指令之前添加以下内容。这将启用运行时边界检查(以及对 STL 容器的许多其他检查),即使您使用通常不检查的 []
运算符:
#define _GLIBCXX_DEBUG 1
在开发/调试期间启用#2 是个好主意。
当我使用向量类时,我发现索引超出向量范围时没有编译错误或运行时错误。问题可以通过以下代码显示
#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。
补充一下其他人所说的:
虽然可以检测到您在编译过程中提到的特定情况——这相对复杂,我不知道有任何 C++ 编译器实际这样做。
如果您使用
g++
及其libstdc++
,您可以在#include
指令之前添加以下内容。这将启用运行时边界检查(以及对 STL 容器的许多其他检查),即使您使用通常不检查的[]
运算符:#define _GLIBCXX_DEBUG 1
在开发/调试期间启用#2 是个好主意。