C ++要求OutputIterator类型X
支持r++
形式的表达式,其中r
是X
的实例。此后缀增量必须在语义上等效于:
(*){ X tmp = r; ++r; return tmp; }
并且必须返回可转换为X const&
的类型。在C ++ 11中,请参见24.2.4(但这不是新的)。在同一部分,它说
输出迭代器上的算法绝不应该尝试两次通过相同的迭代器。它们应该是单通算法。
在上面给出(*),假设我复制了返回值,如X a(r++);
假设r
在递增之前是不可引用的,但未被解除引用。是否要求a
取消引用?如果是,那么X a(r++); *a = t;
必须执行与*r++ = t;
相同的分配吗? a
和r
上是否有(其他)条件?
否则,假设r
在递增之前被解除引用/分配,并且其递增的值(也)是不可引用的。下列哪一项(如果有的话)定义明确:(a)
*a = t;
,(b)++a; *a = t;
,(c)*r = t;
?
另请参阅后续行动:Dereference-assignment to a doubly incremented OutputIterator
答案 0 :(得分:4)
如您所知,r++
具有操作语义
X operator++(int) { X tmp = r; ++r; return tmp; }
我已将返回值添加为X
因为每24.2.2:2 Iterator
满足CopyConstructible
,因此复制构造{{1}的返回值是合法的进入r++
类型的实例。
接下来,X
必须有效;这与*r++ = o
的区别仅在于添加了一个序列点,该序列点与上面操作语义定义中{ const X &a(r++); *a = o; }
之后的序列点合并,因此复合语句具有相同的作为表达陈述的有效性。通过调用return tmp;
,CopyConstructible
具有相同的有效性和操作语义。
在案件中
{ X a(r++); *a = o; }
以下举行:
(a)*r = o;
X a(r++);
无效,因为迭代器的值已被取消引用分配;
(b)*a = o
无效,因为迭代器的值已经增加,违反了单遍要求,因为只需要(新值)++a; *a = o
可递增的:根据24.2.4:2的注释,输出迭代器上的算法永远不应该
尝试两次通过相同的迭代器,虽然未指定传递在此上下文中的含义;
(c)r
有效,因为*r = o
总体上唯一的区别是*r = o; r++; *r = o
的原始值的副本仍然存在,每r
{ 1}}要求对从。
另一个有趣的问题是(对于非解除引用的CopyConstructible
):
r
标准不直接涵盖此标准,但从X a(r);
++r;
++r;
*a = o;
开始它似乎有效。