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

(*){ 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;相同的分配? ar是否有(其他)条件?
  • 否则,假设在递增之前已对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++); *a = o; }的不同仅在于增加了一个序列点,该序列点在上述操作语义定义中与return tmp;之后的序列点合并,因此复合语句与表达式语句具有相同的有效性。通过调用CopyConstructible{ X a(r++); *a = 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/

    10-11 21:02