跳到主要内容

++i 与 i++ 的区别

· 阅读需 2 分钟
El Syzomnia

++ii++ 两者有何区别?

在教学中通常将其描述为:

++i:先自增,后赋值

i++:先赋值,后自增

但事实并不是像看上去那样简单。

问题描述

以下面的代码为例:

int i = 0;
int j = 0;
int k = 0;
int l = 0;

++i;
j++;

cout << i << endl;
cout << j << endl;
cout << ++k << endl;
cout << l++ << endl;

输出结果如下:

1
1
1
0

似乎完全符合。但如果将代码改成下面这样,结果会是什么?

int i = 0;
int j = 0;

i = ++i;
j = j++;

cout << i << endl;
cout << j << endl;

正确答案是:

1
0

是否与你预期的结果不太一致?是的,这就是关键。

分析

从上面的例子我们看出,i++ 并非简单的「先赋值,后自增」。

事实上,用 x86-64 gcc 12.2 编译后查看编译成的汇编代码可知,i++ 创建了一个中间变量,实际参与赋值的是这个中间变量,即

i = i++;

得到如下汇编代码:

mov eax, DWORD PTR [rbp-4]
lea edx, [rax+1]
mov DWORD PTR [rbp-4], edx
mov DWORD PTR [rbp-4], eax

可以视作

int tmp1 = i;
int tmp2 = i + 1;
i = tmp2
i = tmp1;

++i 则不同,它会对原值直接进行操作,即

i = ++i;

得到如下汇编代码:

add DWORD PTR [rbp-4], 1

可以视作

i = i + 1;

这就解释了前面的例子中,为什么 i = ++i 的结果为 1,但 i = i++ 的结果却为 0

补充

当直接单独使用时,即

i++;

++i;

将得到如下汇编代码:

add DWORD PTR [rbp-4], 1

此时经编译器优化,两者并无差别。