简体   繁体   English

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

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

I was working with std::reverse_iterator today and was thinking about how it works with values created by calling begin on a container. 我今天正在使用std::reverse_iterator ,并且正在考虑如何使用在容器上调用begin创建的值。 According to cppreference , if I have reverse_iterator r constructed from iterator i , the following has to hold &*r == &*(i-1) . 根据cppreference ,如果我有从iterator i构造的reverse_iterator r ,则以下必须保持&*r == &*(i-1)

However, this would mean that if I write this 但是,这意味着如果我写这个

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

iter now points to piece of memory that is placed before begin(vec) , which is out of bounds. iter现在指向begin(vec)之前放置的内存begin(vec) ,这是超出范围的。 By strict interpretation of C++ standard, this invokes UB. 通过严格解释C ++标准,这将调用UB。

(There is specific provision for pointer/iterator to element 1-past-the-end of the array, but as far as I know, none for pointer/iterator to element 1-ahead-of-the-start of an array.) (指针/迭代器有一个特定的规定,指向数组的1-last-the-end-end,但据我所知,没有指针/迭代器到数组1的数字开头。)

So, am I reading the link wrong, or is there a specific provision in the standard for this case, or is it that when using reverse_iterator , the whole array is taken as reversed and as such, pointer to ahead of the array is actually pointer past the end? 所以,我读错了链接 ,或者这个案例的标准中是否有特定的规定,或者当使用reverse_iterator ,整个数组被视为反转,因此,指向数组前面的指针实际上是指针过去到底?

Yes, you are reading it wrong. 是的,你读错了。

There is no need for reverse-iterators to store pointers pointing before the start of an element. 反向迭代器不需要存储指向元素开始之前的指针。

To illustrate, take an array of 2 elements: 为了说明,采用2个元素的数组:

int a[2];

These are the forward-iterators: 这些是前向迭代器:

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

The reverse-iterators would be represented with these exact same values, in reverse order: 反向迭代器将以相反的顺序用这些完全相同的值表示:

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

So, while dereferencing a normal iterator is really straightforward, a reverse-iterator-dereference is slightly more complicated: pointer[-1] (That's for random-access iterators, the others are worse: It copy = pointer; --copy; return *copy; ). 因此,虽然解除引用正常的迭代器非常简单,但反向迭代器取消引用稍微复杂一些: pointer[-1] (这是随机访问迭代器,其他更糟糕的是: It copy = pointer; --copy; return *copy; )。

Be aware that using forward-iterators is far more common than reverse-iterators, thus the former are more likely to have optimized code for them than the latter. 请注意,使用forward-iterator比反向迭代器更常见,因此前者比后者更有可能为它们优化代码。 Generic code which does not hit that corner is about as likely to run better with either type though, due to all the transformations a decent optimizing compiler does. 然而,由于所有转换都是一个不错的优化编译器,但是没有碰到那个角落的通用代码很可能在任何一种类型下运行得更好。

std::make_reverse_iterator(begin(vec)) is not dereferenceable, in the same way that end(vec) is not dereferenceable. std::make_reverse_iterator(begin(vec))不可解除引用,与end(vec)不可解除引用的方式相同。 It doesn't "point" to any valid object, and that's OK. 它没有“指向”任何有效的对象,这没关系。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM