c++ - 就序列点而言,前置增量与后增量

标签 c++ c++14 language-lawyer increment undefined-behavior

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/

相关文章:

c++ - 为什么虚拟函数在分配给 'new' 时不能未实现?

c - 未定义行为有多未定义?

c++ - 为什么 container.value_type 在 C++ 中是非法的

c++ - 如何使用 IIOP 和omniORB 进行远程调用

c++ - C++ 中是否可以使用仅堆栈变​​量?

c++ - 涉及指针和手动实现的矩阵类的问题

c++ - 如何解决C++中的异步任务错误

c++ - 当我看到它被删除时,为什么 googlemock 报告泄漏的模拟?

c++ - 在数组大小中使用位操作的原因

c++ - 我对 n3797 8.5.3/5 的解释是否正确?