给定这个有效的 C 或 C++ 代码
int x() {
int numbers[3]; // Lets suppose numbers are filled in with values
int sum = 0;
for (const int* p = &numbers[0]; p != &numbers[3]; ++p)
sum += *p;
return sum;
}
这段代码使用指针算法,据我所知,指针指向数组中最后一个元素是有效的,引用该指针是未指定的,但我们可以有一个指向该位置的指针。 因此,&p[0]、&p[1]、&p[2] 和 &p[3] 是有效指针,p[0]、p[1] 和 p[2] 是有效值。
如果我用 std::vector<int>
替换 int 数组一切都应该没问题,我们得到了这段代码
#include <vector>
int x() {
std::vector<int> numbers(3);
int sum = 0;
for (const int* p = &numbers[0]; p != &numbers[3]; ++p)
sum += *p;
return sum;
}
但是在 Visual C++ 2017 下以 DEBUG 模式运行时,我得到了这个异常“vector 下标超出范围”,这是从 MS STL 库触发的,因为实现假设我们使用 operator[] 自动引用底层值,这是不是这样的。 这是进行边界检查的 MS STL 代码...
_NODISCARD _Ty& operator[](const size_type _Pos)
{ // subscript mutable sequence
#if _ITERATOR_DEBUG_LEVEL == 2
if (size() <= _Pos)
{ // report error
_DEBUG_ERROR("vector subscript out of range");
}
#elif _ITERATOR_DEBUG_LEVEL == 1
_SCL_SECURE_VALIDATE_RANGE(_Pos < size());
#endif /* _ITERATOR_DEBUG_LEVEL */
return (this->_Myfirst()[_Pos]);
}
如果我用 numbers.begin() 和 numbers.end() 替换 &numbers[0] 和 &numbers[3],我不会收到错误。
我同意这确实是丑陋的代码,但我简化了真正的代码只是为了暴露错误。
原始代码是在具有零元素的 vector 上使用 &vec[0]。
所以我的问题是:
这是 Microsoft Visual C++ STL 实现上的 BUG,还是对 vector <> 的运算符 [] 有一些限制?
我知道用 at() 替换 [] 会是一个错误,但我知道 &vec[size] 对 std::vector<>
应该仍然有效最佳答案
用&p[n]
获取指向最后一个元素的指针是否定义明确,一直是一个灰色地带。
但是,指向最后一个元素之后的指针是明确定义的。
您可以通过使用普通指针算法来避免此类错误:
for (const int* p = numbers.data(); p != numbers.data() + 3; ++p)
或者,更一般地说,迭代器:
using std::begin;
using std::end;
for(auto p = begin(v), q = end(v); p != q; ++p)
或者使用 range for 循环:
for(auto const& element : v)
没有充分的理由使用 v[v.size()]
,真的。
关于c++ - 使用 operator[] 引用 std::vector<> 上最后一个元素的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52973814/