9

在 pre-Range TS 代码中,我可能会执行以下操作来获取对 ForwardIterator 值的(可能可修改的)引用:

auto &val = *it;

这也将用于for此类迭代器的基于范围的循环中:

for(auto &val : some_range)

但是,在基于 C++20 和 Range TS 的代码中,我看到auto&&在这些位置有很多使用。auto&&我从语言的角度理解正在做什么。我不明白为什么在这些地方使用它,什么时候auto&应该可以正常工作?大多数这种性质的代码都不会转发引用,那么为什么要使用转发引用来捕获它呢?

4

1 回答 1

13

使用这个成语是因为 Range TS 和 C++20 等效项实际上需要这个成语。这个要求的原因与代理迭代器现在是所有类型的迭代器的合法构造有关。

代理迭代器operator*不返回value_type&; 它返回一个像引用一样的对象的prvalue 。因此,如果您尝试使用 存储对值的引用auto&,您的代码将无法使用代理迭代器进行编译。

Range TS 的迭代器概念从不要求 from 的返回值operator*实际上是语言引用。Readable 概念只要求返回值可转换为value_type. Writable 概念只要求value_type可以将 a 分配给返回值。

因此,从 Range 功能下的各种迭代器获取引用的代码现在必须使用auto&&,它可以绑定到纯右值而不需要生成它们const。因此,在处理范围时,如果您想获得对该值的可能非常量的引用,auto&&是最方便的方法。如果您只想要一个const参考,您可以继续使用const auto &.


请注意,auto&&它还处理直接value_type从其operator*. 显然,这些仅对 Readable 迭代器有用,但它们非常有用。最简单的例子是在一些整数上的计数范围的迭代器。迭代器返回一个int,而不是对某些内存的引用。由于没有返回语言参考的硬性要求,因此此类迭代器可以是 Range TS 中的 RandomAccessIterators。

这样的迭代器对于正则表达式匹配也很有意义。当前regex_iterator返回对内部对象的引用;这是成为 ForwardIterator 所必需的。operator*相反,通过进行搜索并将匹配对象作为纯右值返回,它可能会小得多。但是旧系统不允许这样做。

给定这样的迭代器,auto&不能用于捕获对其结果的“引用”。

于 2018-07-22T01:21:50.507 回答