正在递减离端迭代器
Decrementing an off the end iterator
我今天读到关于支持双向迭代的容器如何使用这段代码:
Collection c(10, 10);
auto last = --c.end();
*last;
这让我思考,当向STL中定义了--end的算法提交一对双向迭代器[beg,end)时,是否需要?如果是,结果是否应该是可引用的?
即
void algo(T beg, T end){
//...
auto iter = --end;
//...
*iter;
}
如果算法需要由双向迭代器first
和last
定义的范围,则--last
需要在与++first
相同的条件下有效,即范围不为空。当且仅当first == last
。
如果该范围不为空,则--last
的计算结果为引用该范围中最后一个元素的迭代器,因此*--last
确实也需要有效。
也就是说,没有那么多标准算法专门需要双向迭代器(并且不需要随机访问)。prev
、copy_backward
、move_backward
、reverse
、reverse_copy
、stable_partition
、inplace_merge
、[prev|next]_permutation
。
如果你看看其中一些算法的作用,你应该会发现该算法通常会减少范围结束迭代器并取消引用结果。
正如James所说,对于容器,函数end()
按值返回迭代器。对于迭代器来说,当x
是该类型的右值时,--x
应该是一个格式良好的表达式,这并不是一个普遍的要求。例如,指针是双向迭代器,声明为int *foo();
的函数按值返回指针,而--foo()
不是格式良好的表达式。恰好,对于您在实现中看到的容器,end()
返回一个类类型,该类类型将operator--
定义为成员函数,因此代码进行编译。它也能工作,因为容器不是空的。
请注意,在这方面存在差异
auto last = --c.end();
与。
auto last = c.end();
--last;
前者递减右值,而后者递减左值。
你读错了。表达式--c.end()
从未被授权。如果迭代器至少不是双向的,事实上,它是明确的禁止,并且需要编译器错误。如果集合为空,这是未定义的行为。在所有其他情况下,如果它可以编译,但不能保证它会编译。它失败了使用std::vector
的许多早期实现进行编译例如,迭代器只是指向指针的typedef。(实际上,我正式地认为,在所有情况下,这都是未定义的行为,因为您违反了对模板化实现的约束。在里面练习,不过,你会得到我刚才描述的。)
可以说,因为它没有保证,一个好的实现将导致它无法系统地编译。由于各种原因,大多数人没有。不要问我为什么,因为让它失败非常简单系统地:只需使迭代器上的operator--
免费函数,而不是成员。
编辑(附加信息):
事实上,不需要它可能是CCD_ 26和CCD_。当然我做过的每一个项目都有它们。正确的方式写这是:
prev( c.end() );
当然,迭代器是双向的或更好的是,容器不是空的,仍然可以容纳。
每个算法都会告诉您它需要什么类型的迭代器。当双向迭代器被调用时,它自然需要支持递减。
CCD_ 28是否可能取决于CCD_。
只有需要双向迭代器的算法才需要它。
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 如何在c++迭代器类型中包装std::chrono
- 集合上的输出迭代器:assign和increment迭代器
- Boost Spirit,获取迭代器内部语义动作
- 对于set上的循环-获取next元素迭代器
- 为什么output_editor Concept不需要output_e迭代器标记
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 使用迭代器时如何访问对象在向量中的位置?
- std::vector::迭代器是否可以合法地作为指针
- 跟随整数索引列表的自定义类迭代器
- 不明白迭代器,引用和指针失效,一个例子
- 我可以使用反向迭代器作为ForwardIt吗
- ESP8266单片机矢量迭代器的C++问题
- 如何在C++中将迭代器作为函数参数传递
- 是否应避免从非常量迭代器转换为常量迭代器?
- 如何在 c++ 中将字符串迭代器变量传递给函数?
- 为什么 vector 的随机访问迭代器给出与指针不同的内存地址?
- 为什么 C++ std::unordered_map 从 emplace/ 找到返回一个迭代器?