++i 与 i++ 的区别
· 阅读需 2 分钟
++i
与 i++
两者有何区别?
在教学中通常将其描述为:
++i
:先自增,后赋值
i++
:先赋值,后自增
但事实并不是像看上去那样简单。
问题描述
以下面的代码为例:
int i = 0;
int j = 0;
int k = 0;
int l = 0;
++i;
j++;
std::cout << i << std::endl;
std::cout << j << std::endl;
std::cout << ++k << std::endl;
std::cout << l++ << std::endl;
输出结果如下:
1
1
1
0
似乎完全符合。但如果将代码改成下面这样,结果会是什么?
int i = 0;
int j = 0;
i = ++i;
j = j++;
std::cout << i << std::endl;
std::cout << j << std::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
此时经编译器优化,两者并无差别。