C++ OutputIterator 后递增要求

标签 c++ iterator post-increment

C++ 要求 OutputIterator 类型 X 支持 r++ 形式的表达式,其中 rX。此后缀增量必须在语义上等同于:

(*) { X tmp = r;++r;返回 tmp; }

并且必须返回可转换为 X const& 的类型。在 C++11 中,请参阅 24.2.4(但这不是新的)。在同一部分,它说

Algorithms on output iterators should never attempt to pass through the same iterator twice. They should be single pass algorithms.

给定 (*),上面,假设我复制返回值,如 X a(r++);

  1. 假设 r 在递增之前是可解引用的,但没有被解引用。是否要求 a 是可解引用的?如果是这样,必须 X a(r++); *a = t; 执行与 *r++ = t; 否则相同的赋值? ar 是否有任何(其他)条件?

  2. 否则,假设 r 在递增之前被取消引用/赋值,并且它的增量值(也)是可取消引用的。以下哪项(如果有的话)是明确定义的:(a) *a = t;, (b) ++a; *a = t;, (c) *r = t;?


另见后续:Dereference-assignment to a doubly incremented OutputIterator

最佳答案

正如您所注意到的,r++ 具有操作语义

X operator++(int) { X tmp = r; ++r; return tmp; }

我将返回值添加为 X 因为根据 24.2.2:2 Iterator 满足 CopyConstructible,所以复制是合法的将r++的返回值构造成X类型的实例。

接下来,要求*r++ = o有效;这不同于 { const X &a(r++); *一=o; }只是增加了一个序列点,与上面操作语义定义中的return tmp;之后的序列点合并,所以复合语句有与表达式语句具有相同的有效性。通过调用 CopyConstructible{ X a(r++); *一=o; 具有相同的有效性和操作语义。

在案例中

*r = o;
X a(r++);

以下内容:

  • (a) *a = o 无效,因为迭代器的那个值已经被解除引用分配;

  • (b) ++a; *a = o 无效,因为迭代器的值已经递增,违反了单遍要求,因为只有 r 的(新值)需要递增:根据 24.2.4:2 的注释,输出迭代器上的算法永远不应该 尝试两次通过同一个迭代器,尽管没有指定通过在此上下文中的含义;

  • (c) *r = o 是有效的,因为唯一的区别是 *r = o; r++; *r = o 总体上是 r 原始值的拷贝的继续存在,根据 CopyConstructible 要求对从中复制的值没有语义影响.

另一个有趣的问题是(对于非解引用分配的 r):

X a(r);
++r;
++r;
*a = o;

标准没有直接涵盖这一点,但从 CopyConstructible 看来它应该是有效的。

关于C++ OutputIterator 后递增要求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11876128/

相关文章:

c++ - Visual Studio 联编文件项目的自定义平台

java - 如何计算位于给定数组的两个元素之间的数组元素的数量

c - 前后增量运算符分析结果

c - 不同的输出

c++ - 不处理 asio 异步操作

c++ - abs() 对一些非常大的 double 值返回负值

c++ - 为什么继承的函数会忽略在原始函数中调用的重写函数?

java - 如何从同一个 it.next() 获取多个值

c++ - 两个数组的 STL 兼容迭代器

c++ - 如果条件为 TRUE,则在 do while 循环中发布增量(最好的方法?)