c++ - 使用 operator[] 引用 std::vector<> 上最后一个元素的问题

标签 c++

给定这个有效的 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/

相关文章:

c++ - C++ 中的 I/O 运算符重载错误

c++ - 字符串格式用\0填充?

c++ - ./libmylib.so : undefined reference to `submarinex::LIB::kCount'

c++ - 为什么我的字符串第二次没有正确接受输入?

c++ - 为什么这段代码会无限循环

c++ - 为什么两个迭代器在循环中分开?

c++ - 释放内存,Windows 已触发断点

c++ - 如何正确使用c++中的cin.fail()

c++ - 在没有 dynamic_cast 的情况下确定大层次结构中基指针的真实类型

c++ - 使用 char** argv 时如何避免指针运算