为什么使用 'std::reverse_iterator' 不会调用 UB?
Why using `std::reverse_iterator` doesn't invoke UB?
我今天正在使用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)
也不可解引用。它不"指向"任何有效的对象,这没关系。
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 通过reinterpret_casting方法指针从指针调用派生类的方法。这是 UB 吗?
- 为什么从构造函数对纯虚函数的虚拟调用是 UB,而标准允许调用非纯虚函数
- 具有typeid调用的UB
- 为什么使用 'std::reverse_iterator' 不会调用 UB?
- 如果从析构函数调用纯虚函数是UB,为什么可以使用纯虚析构函数?
- 函数调用中的临时:UB