为什么 i = ++i + 2 是未定义的行为?

why i = ++i + 2 is undefined behavior?

本文关键字:未定义 ++i 为什么      更新时间:2023-10-16

我读过一些关于评估顺序的东西,我理解由评估顺序引起的一些错误。

我的基本规则来自文本和示例:

  • 操作数计算的顺序与优先级和关联性无关。
  • 在大多数情况下,顺序在很大程度上是未指定的。

所以对于这样的表达:int i = f1() * f2();

必须先调用 f1 和 f2,然后才能完成乘法。毕竟,是他们的结果成倍增加。但是,我们无法知道 f1 是否会在 f2 之前调用,反之亦然。

未定义的行为示例:

int i = 0;
cout << i << " " << ++i << endl; 

我如何理解:我将i++i视为一种功能。我不知道哪个先评估,所以第一个i可能是01,(规则(是有意义的。


while(beg != s.end())
*beg = toupper(*beg++);  //Just another example.

我认为理解这一点的关键是将每个操作数视为一个"评估单元",人们不知道这些单元内的评估顺序,但可以知道每个单元中的顺序。

但在这里供i = ++i + 2参考,为什么是错的? 我无法用我自己的结论来解释。

i用作左值而不是指针++i只是重写原始值,不会更改存储地址。如果它先评估还是后评估,可能会出错?我的规则在这里失败了。

很长,但尽量提供足够的背景信息,感谢您的耐心等待。


我不知道答案中经常提到的序列点。所以我想我需要先阅读一些关于它的东西。顺便说一句,辩论不是很有帮助,因为新手只是想知道为什么它被认为是错误的,就像 C++11 之前一样?


我发现这个答案 未定义的行为和序列点很好地解释了为什么i = ++i + 2C++11 之前是未定义的行为

C++11 有了新的排序规则。特别是,对于预递增(++i(,副作用(写入新值(在进一步使用新的递增值之前被排序。由于赋值i=是在评估其右侧之后排序的,这意味着写++i在写i=(++i + 2)之前传递排序

这对i=(i++ + 2)来说将是另一回事.对于后递增,副作用是后排序的,这意味着两个赋值不再相对地排序。这是未定义的行为。

i = ++i + 2中的两个"子函数"是由=运算符进行的显式赋值和由++运算符完成的隐式赋值。

preincrement 运算符被定义为返回变量的增量值,这绝对应该用于加法(由+运算符执行(。但是,它没有定义,何时应将递增的值存储回i

因此,无法确定i的最终值是old_i incremented plus 2还是只是old_i incremented