post-增量运算符如何精确工作。有一些例外吗?

How the post-increment operator works exaclty. Are there some exceptions?

考虑这段代码

int j = 0;
int x = 0;

for(int i=0;i<5;i++){
    j = x++;
    cout<<x<<" ";
}

输出:

1 2 3 4 5

现在考虑这个

int j=0;

for(int i=0;i<5;i++){
    
    j = j++;
    cout<<j<<" "; 
}

输出:

0 0 0 0 0

我的疑惑是为什么j在赋值为0后没有递增。 j=j++; 不等于 j = j; j++; 吗?如果不是,那么第一种情况是怎么回事。我知道这是一个愚蠢的疑问,但我自己无法弄清楚。

My doubt is why is j not being incremented after it is assigned the value 0. Isn't j=j++; equivalent to j = j; j++; and if it isn't then what's going on with the first case.

否,因为 j = j++; 未定义。请参阅 https://en.wikipedia.org/wiki/Undefined_behavior#Examples_in_C_and_C++

中的此示例和其他示例
j = j++;
  • 首先,right-hand 侧表达式求值,即 j++.
  • 我们知道 j++ returns j 的前一个值(即递增 j 之前的值)。所以,这里 j++ returns 0.
  • 最后变成了j = 0;

每次迭代都会发生同样的事情,这就是只打印 0 的原因。

注:

正如其他人提到的,这是 C++17

定义的行为

这是 c++11 下的未定义行为,clang++ 和 g++ 都抱怨它。

test.cpp:7:10: warning: multiple unsequenced modifications to 'j' [-Wunsequenced]
    j = j++;
      ~  ^
1 warning generated.

但它在 c++17 中不再是 ub。

j = j++;

导致undefined behavior,C++中有一个sequence point的概念,参见: https://en.wikipedia.org/wiki/Sequence_point

Isn't j=j++; equivalent to j = j; j++;

不绝对不是,这是对前置和 post 增量运算符最常见的误解之一。

j = j++; 的真正等价物是

int temp = j;
++j;
j = temp;

初学者认为 post 增量发生在其他一切之后。但事实并非如此。增量发生在取值之后,而不是在语句的其余部分执行之后。可以看到在上面的代码中,j取值temp = j;,然后自增发生++j;,然后取值j = temp;.

正如已经多次提到的,此代码仅在 C++17 中具有定义的含义,在此之前它是未定义的。