【问题标题】:Why are C++ iterators required to return a reference?为什么需要 C++ 迭代器来返回引用?
【发布时间】:2018-03-19 12:07:31
【问题描述】:

我正在实现一个迭代器,它对生成器函数的结果进行迭代,而不是对内存中的数据结构(例如向量或映射)进行迭代。

通读final working draft for C++17 §27.2.3,输入迭代器(以及大多数其他迭代器)的解引用运算符的返回类型 a forward iterator 必须是引用.这对于迭代器正在迭代的数据结构中存在的项目很好。但是,因为我没有使用数据结构并且在调用取消引用运算符时正在计算每个项目,所以我没有有效的返回引用;当操作员返回时,计算的项目被销毁。为了解决这个问题,我将计算结果存储在迭代器本身并返回对存储结果的引用。这适用于我的用例,但在与任意用​​户定义类型一起使用时会出现问题。

我可以理解 允许 迭代器返回引用,但为什么这是非变异迭代器的要求?标准的作者是否没有将生成器和动态转换视为迭代器的有效用例?返回值而不是 const 引用会造成任何实际伤害吗?

[edit]:出于对为什么标准的编写方式的好奇,我提出了更多的问题,因为我已经有了一个非常好的解决方法。

【问题讨论】:

  • 我认为锻炼答案(来自专家)的一个很好的例子是std::istream_string。话虽如此,我的直觉是返回一个值 T 并不比返回一个 const T& 好,因为在某些情况下,取消引用可能希望返回一个实际的临时值,而在其他时候它想返回一个实际预先存在的元素。
  • @alfc 没有 istream_string 这样的东西。你的意思是字符串流吗?因为它不使用迭代器,如果它使用了它返回的字符仍然会来自某个地方的缓冲区。
  • 啊,我明白了,它是 istream_iterator。
  • 是的,我是这个意思。
  • 这很奇怪,因为纯右值上的本地 const T& 会延长纯右值的生命周期,直到引用范围结束。似乎大多数假设 Forward(或更高版本)输出迭代器返回 const T& 的算法都适用于纯右值。但我理解措辞似乎不同意这一点

标签: c++ iterator std standard-library c++-standard-library


【解决方案1】:

解除对输入迭代器的引用不需要来产生一个glvalue(即返回一个引用)。输入迭代器要求说解引用时的返回类型必须是“reference,可转换为T”,但没有说reference 必须是引用类型。

然而,为了产生一个泛左值,需要解引用一个前向迭代器

如果X 是可变迭代器,reference 是对T 的引用;如果X 是一个常量迭代器,reference 是对const T 的引用,

所以继续写你的迭代器,它可以动态生成元素,但它只能是输入迭代器,不能是前向迭代器。对于许多算法来说,这已经足够了(例如,std::for_eachstd::all_of)。

【讨论】:

  • 很高兴知道,当标准说reference 时,它们并不意味着“参考”。如果是这样,很多事情对我来说开始变得更有意义了。
  • @alfC 如果这个答案对你有帮助,请考虑接受它
  • 好的,所以X::reference 不需要是输入迭代器的实际引用类型(考虑到名称,这有点奇怪和意外)。这仍然没有回答为什么根据标准,更专业的迭代器需要返回一个实际引用的reference
  • 确实如此,但我认为性能不会定义一个概念。所有这些算法都可以正常编译。
  • @alfC,我同意 mgoldman。我只是在编写一个算法迭代器(或者它是一个迭代器算法?),其中一个“容器”被赋予了两组开始和结束迭代器(IT1IT2)并通过一个迭代器计算结果。取消引用迭代器时的返回类型是std::pair<T1*, T2*>,其中.first.second 可能指向迭代器之一在它们走到其末端迭代器时指向的元素,或者可能是nullptr。如果前向迭代器必须是const T&,这是否会使我的迭代器成为迭代器无效?这在什么情况下不会正确执行?
猜你喜欢
  • 2017-03-19
  • 2013-06-22
  • 1970-01-01
  • 2010-11-16
  • 2014-02-16
  • 2016-09-23
  • 2016-08-01
  • 2017-02-19
  • 1970-01-01
相关资源
最近更新 更多