在this answer有一些定义明确和未定义的表达式的示例。我对其中两个特别感兴趣:
(6) i = i++ + 1; // Undefined Behaviour
(7) i = ++i + 1; // Well-defined Behaviour
这意味着前增量和后增量在序列点和定义明确/未指定/未定义的行为方面存在差异,但我不明白这种差异从何而来。
在标准草案 (N4618) 中有一个代码示例 ([intro.execution], pt 18)
i = i++ + 1; // the value of i is incremented
i = i++ + i; // the behavior is undefined
据我所知,这意味着表达式 i = i++ + 1
应该定义明确并且变量 i
的值应该增加 1
作为此表达式的结果。但是,在 MSVS 2015 中运行的这段代码将 i
增加了 2
。
那么,表达式 i = i++ + 1
会发生什么?它是明确定义的、未定义的、实现定义的还是未指定的行为?如原始答案中所述,就序列点和 UB 而言,此表达式和类似表达式中的预增量和后增量之间有什么区别吗?以及为什么 Visual Studio 显示的行为不同于标准编写的行为?
另请注意,我主要对现代 C++ (14/17) 感兴趣。
最佳答案
表达式 i = i++ + 1
会发生什么?它是明确定义的、未定义的、实现定义的还是未指定的行为?
标准中给出了这个确切的例子,我们有多幸运?
N4296 1.9.15 [intro.execution]
i = i++ + 1; // the behavior is undefined
当然,我们也想知道原因。以下标准报价似乎与此相关:
N4296 1.9.15 [intro.execution]
[ ... ] The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. [ ... ]
这告诉我们求和将发生在赋值之前(呃,它怎么知道要赋值什么!),但它不能保证增量将发生在赋值之前或之后,现在我们在浑水……
N4296 1.9.15 [intro.execution]
[ ... ] If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, and they are not potentially concurrent (1.10), the behavior is undefined. [ ... ]
赋值运算符对i
的值有副作用,这意味着我们有两个副作用(另一个是i++
执行的赋值)标量对象,未排序,未定义。
为什么 Visual Studio 显示的行为与标准编写的不同?
事实并非如此。标准说它是未定义的,这意味着它可以做任何你想做的事情,也可以做完全不同的事情,这恰好是编译器吐出的行为!
关于c++ - 就序列点而言,前置增量与后增量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42997644/