类别: 迭代器 | 组件类型: 概念 |
X | 输出迭代器模型的类型 |
x, y | 类型对象X |
执行任何非平凡的转换。输出迭代器可能是*奇异的*,这意味着大多数操作(包括复制和解引用赋值)的结果都是未定义的。唯一保证支持的操作是将非奇异迭代器赋值给奇异迭代器。
输出迭代器可能是*可解引用的*,这意味着通过它进行赋值是定义良好的。可解引用迭代器始终是非奇异的,但非奇异迭代器不一定是可解引用的。
名称 | 表达式 | 类型要求 | 返回类型 |
---|---|---|---|
默认构造函数 |
X x; X() |
||
复制构造函数 | X(x) | X | |
复制构造函数 | X y(x);或者X y = x; | ||
解引用赋值 | *x = t | t可转换为X. [1] | 的值类型集中的类型 |
结果未使用 | 前缀递增 | ++x | |
X& | 后缀递增 | (void) x++ | |
void | 后缀递增并赋值 | 的值类型集中的类型 |
名称 | 表达式 | 表达式语义 | 前提条件 | 语义 |
---|---|---|---|---|
默认构造函数 |
X x; X() |
x后置条件 | ||
复制构造函数 | X(x) | x可能是奇异的 | 是非奇异的*X(x) = t*x = t [2] | |
复制构造函数 | 等价于或者X x(y); | y可能是奇异的 | X x = y;*X(x) = t*x = t [2] | |
解引用赋值 | *x = t | x*y = tx是可解引用的。如果之前已经通过 | ||
结果未使用 | 前缀递增 | x进行过赋值,则已经进行过一次递增。 [3]x是可解引用的。x之前已经通过x [3] [4] | x进行过赋值。如果 | |
X& | 后缀递增 | x进行过赋值,则已经进行过一次递增。 [3]x之前已经递增过,则已经通过 | 进行过一次赋值。指向可以存储值的下一个位置 | x进行过赋值。如果 |
void | 后缀递增并赋值 | x*y = tx之前已经通过 | 进行过一次赋值。进行过赋值。 | x进行过赋值。如果 |
insert_iteratorfront_insert_iteratorback_insert_iterator*x = t注意front_insert_iterator[1] 其他迭代器类型,包括 平凡迭代器 和 输入迭代器,定义了*值类型*的概念,即迭代器被解引用时返回的类型。然而,这个概念不适用于输出迭代器,因为解引用运算符(一元*x = toperator*operator=)不会为输出迭代器返回可用的值。解引用运算符可以使用的唯一上下文是通过输出迭代器进行赋值
。尽管 输入迭代器 和输出迭代器是大致对称的概念,但在访问和存储值方面有一个重要的区别:对于 输入迭代器x必须返回唯一的类型,但是对于输出迭代器,在表达式y中,没有理由要求y必须采用唯一的类型。 [5] 因此,输出迭代器不需要有任何唯一的“值类型”。
[2] 在任何时候,单个输出迭代器都应该只有一个活动副本。也就是说:在创建并使用输出迭代器x的副本x之后,不应再使用原始输出迭代器x。x[3] 通过输出迭代器进行赋值应该与递增交替进行,并且在递增之前必须通过应该与递增进行赋值。任何其他操作顺序都会导致未定义的行为。也就是说{*x = t
; ++x; *x = t2; ++x}是可以接受的,但; ++x; ++x; *x = t2;}则不行。[4] 请注意,输出迭代器不需要定义相等比较。即使定义了operator==.
,Xx == y*x = t也不一定意味着++x == ++y[5] 如果您正在实现输出迭代器类,定义的一种合理方法是将X::operator*()定义为返回某个私有类X::operator*()X_proxyX.