为什么使用 'std::reverse_iterator' 不会调用 UB?

Why using `std::reverse_iterator` doesn't invoke UB?

本文关键字:调用 UB iterator std 为什么 reverse      更新时间:2023-10-16

我今天正在使用std::reverse_iterator,并正在考虑它如何与在容器上调用begin创建的值一起工作。根据cppreference,如果我用iterator i构造reverse_iterator r,下面必须保存&*r == &*(i-1)

然而,这意味着如果我写这个

std::vector<int> vec = {1, 2, 3, 4, 5};
auto iter = std::make_reverse_iterator(begin(vec));

iter现在指向begin(vec)之前的一块内存,这是越界的。根据c++标准的严格解释,这调用了UB。

(有特定的指针/迭代器指向数组末尾之后的元素1,但据我所知,没有指针/迭代器指向数组开始之前的元素1)

所以,我读的链接是错误的,或者在这种情况下的标准中是否有特定的规定,或者当使用reverse_iterator时,整个数组被视为反向的,因此,指向数组前面的指针实际上是指针过去的结束?

是的,你看错了。

不需要反向迭代器存储指向元素开始前的指针。

以包含两个元素的数组为例:

int a[2];

这些是正向迭代器:

a+0 a+1 a+2 // The last one is not dereferenceable

反向迭代器将用以下完全相同的值表示,只是顺序相反:

a+2 a+1 a+0 // The last one cannot be dereferenced

因此,虽然对普通迭代器解引用非常简单,但反向迭代器解引用稍微复杂一点:pointer[-1](这是针对随机访问迭代器的,其他更糟糕:It copy = pointer; --copy; return *copy;)。

请注意,使用前向迭代器比使用反向迭代器要常见得多,因此前向迭代器比反向迭代器更有可能为它们优化代码。没有碰到那个角落的泛型代码很可能在任何一种类型下运行得更好,尽管,由于一个体面的优化编译器所做的所有转换。

std::make_reverse_iterator(begin(vec))不可解引用,同理end(vec)也不可解引用。它不"指向"任何有效的对象,这没关系。