这是一个愚蠢的问题。 :)
[编辑:无论愚蠢与否,这实际上是一个关于C++的奇特问题,请参见UPDATE_2]
假设我们有:
int a = 0; // line 1
int b = ++a; // line 2
第二行发生的是(注意,数字只是标记,不指定确切的顺序):
= [1: write result of (3) to result of (2)]
/\
[2: take "b" l-value] [3: convert result of (4) to an r-value ]
|
[4: take "a" l-value, "increment" and return it]
在(4)中的“write”在(3)中的“read”之前是“有序的”,由于它们之间没有序列点,因此副作用不能保证在(3)之前发生(在(4)本身还有一个“read”,但是在“write”之前有序,因此不会导致未定义行为)。
那么,以上哪里出了问题?
换句话说,问题在哪里?
似乎存在一种“竞争”,即l值到r值转换(“读取”)或增量(“写入”)副作用先发生。
在C语言中,这将导致UB,根据JTC1/SC22/WG14 N926 "Sequence Point Analysis"*(例如,EXAMPLE 5:
int x,y; (x=y) + x; // UB
)。请注意,如果使用后自增,则不会出现这种情况,因为(3)和(4)将构成单个 [(3):获取“a”的l值,将其转换为r值并返回该r值] ,“写入”副作用延迟到下一个序列点之前的某个时间才会发生
_
(*) 这似乎是C99标准委员会成员提供的最清晰系统的理论基础。
[更新_2]
教训:永远不要用C的规则来评判C++ :))。我曾经这样做,想知道为什么N926(清楚地描述了C99的事情)在前置增量产生l-value的主题上“不够清楚”。
问题是如何为C++构建类似的理论基础,因为并没有一个,即使在C的情况下,仅仅解释标准也非常困难,而C ++语言标准更加复杂和晦涩。
[更新_3]
有一个讨论涉及一些相关主题(至少在较新的一半中)"关于常见表达式的未定义性问题。", 此外,委员会成员在这里讨论了该问题(请参见“222.序列点和左值返回运算符”)。