优秀的编程知识分享平台

网站首页 > 技术文章 正文

C++学习点滴:++i 与i++的区别的挖呀挖

nanyue 2024-07-26 15:38:20 技术文章 10 ℃

一般初学C++的人,会对‘++i ’与‘i++’的具体区别不加理会的,这也包括本人。但,因最近无意中看到网上的人讲解这个表达式‘i = (i++) + (++i) + ++i’是怎么计算时,可惜他解释得也不清楚,引起本人极大的兴趣,因而本人决定自己对其区别进行挖呀挖式的探秘。现将自己所体会到向大家分享一下。
一.两者的基本性质区别(编译器的处理方式不同)
++i和i++都是表示自增运算,但编译器对它们处理方式是不同的,不同之处在于执行的顺序和返回的结果。对于‘++i’,i的值递增,表达式的值是i的新值,编译器的处理方式是首先将它递增,然后再为表达式赋值;对于‘i++’,i 的值是递增的,但表达式的值是 i 的原始值,编译器的处理方式是首先将它为表达式赋值,然后递增变量i。用代码来理解表达,则为:‘++i’是i += 1,return i;而‘i++’是int temp = i、i += 1,return temp 另外在赋值上虽然它们都可以作为右值但只有++i可以作为左值,例如 ++i = 7,这个语句将把7赋给i,并且将i的值增加1。概述两者的区别如下:
1、i++ 返回原来的值,++i 返回加1后的值;
2、i++前者是先赋值,然后再自增;++i后者是先自增,后赋值;
3、两者可作为右值,i++不能作为左值,而++i可以,如 ++i=7。

二.两者在运算速度上的比较
对于运算速度的比较,
++i只是微级领先两者速度可算是根本上是一样的!(此是网上某些C++大神测试后的表述,因为‘i++’CPU会创建临时变量放在寄存器内,再将临时变量赋给i ,而++i不产生临时变量,因此 ‘++i’在速度上微快些!)下面本人通过在For循环运算中分别使用i++与++i的来比较说明其运算时间和汇编代码的区别,代码如下:
#include<iostream>
#include <stdio.h>
#include <math.h>
#include <windows.h> //LARGE_INTEGER 要使用的头文件
using namespace std;
int main()
{
long sum =0;
LARGE_INTEGER cpuFreq;
LARGE_INTEGER startTime;
LARGE_INTEGER endTime;
double runTime =0.0;
QueryPerformanceFrequency(&cpuFreq);
QueryPerformanceCounter(&startTime);
for(int i=0;i<
20000001;i++) //进行2000万次相加运算
//for(int i=0;i<
20000001;++i)
{
sum =sum+i; }
QueryPerformanceCounter(&endTime);
runTime = (((endTime.QuadPart - startTime.QuadPart) * 1000.0f) / cpuFreq.QuadPart);
cout<<"sum= "<<sum<<endl;
cout<<"此使用i++运算需时:"<<runTime<<"毫秒"<<endl;
//cout<<"此使用++i运算需时:"<<runTime<<"毫秒"<<endl;
system("pause");
return 0;
}
********
运算结果如下图示:(说明:两者的编译状况是一致的)



********
汇编代码比较如下图示:(两者的汇编代码是一样的)



三.着重讲述表达式中出现
多个‘++’的计算方法

当然,对于单条‘++’运算,C++ 小白是很容易理解的,
但对于出现多个++的运算时,其计算可令人惘然,如下面计算式(变量的初始值均设置为0):
i = (i++) + (++i);(
混合运算并给自己赋值
i = (i++) + (++i) + ++i;
i = (i++) + ++i + (i++) + (++i);
b = (i++) + ++i + (i++) + (++i);//
混合运算但给其它变量赋值
i = i++ + ++i + i++ + ++i;//
无括号和混合的运算并给自己赋值
c = ++i + ++i + i++ + ++i ;//
无括号和混合的运算但给其它变量赋值
(i++) + ++i + (++i) + i++;//混合运算但
无给变量赋值
i++ + (++i)+ ++i + (i++);
i = (i++) + (++i) + (++i) + (i++) + (++i);
d = (i++) + (++i) + (++i) + (i++) + (++i);
i = i++ + ++i + ++i + i++ + ++i;/
/无括号和无混合的运算并给自己赋值
i = (i++) + (i++) + (i++) + (i++) + (i++);
i = (++i) + (++i) + (++i) + (++i) + (++i);
j = (i++) + (++i) + (++i) + i++ + (++i)+ i++ + (i++)。
其运算真是让人摸不着头脑的!现先看看
其编程运算的结果如下图示:


程序的代码如下图示:



其反汇编代码为(展示7个运算式的代码图):







通过观摩编译器的汇编代码后,本人领略出编译器在混合和无混合两种情况下的运算机制(方法),现结合以i = (i++) + (++i) + (++i) + (i++) + (++i)的运算式为例,仅讲述在混合情况下的运算机制:
1.编译器对‘
++’运算符的处理等级要优先于‘()’,因此有无括号来括住运算式,其计算结果都是是一样
2.计算时,
先将计算式中的所有前置‘++i’放在前面(左边),将计算式中的所有后置‘i++’放在后面(右边),即先进行对所有的‘++i’操作
3.
再对运算式分别统计出n1个‘++i’(本例有3个)和n2个‘i++’(本例有2个)运算式;
4.然后先将‘++i’运算式中的i值进行n1次(本例3次)加1自增操作,得到结果值为n1(本例为3),并将此值n1赋给i(本例此时i=3);
5.
以此i的值来代入所有计算式(n1+n2个,本例为5个)中进行相加操作,以本例来计算,即(i=3)+(i=3)+(i=3)+(i=3)+(i=3)=15;
6.
再补计算未进行自加1操作的‘i++’的n2个运算式(本例2个),以本例来计算,即增2次加1操作,结果为2,最后将此值与上一步所计算出的结果值(15)相加后所得的最终值(2+15=17)赋给i,此时i的值为17。 (计算完成)
因而i = (i++) + (++i) + (++i) + (i++) + (++i)的运算式则手动计算方法为:
1.先重排序:i =(++i) + (++i) + (++i) + (i++) + (i++) ;
2.对i进行3次自增1计算:i= 0 + 1 + 1 + 1 = 3;
3.将i=3代入整条运算式中(不理会式中“++”符号):3+3+3+3+3 =15;
4.补算2个未进行加1操作“i++”:1+1=2;
5.
再合并计算最终结果值:2+15=17 。(计完)
(无混合情况下的运算机制留给读者自己去琢磨)
四.现再比较‘i++’与 ‘++i’作为For循环中使用的参数的运算区别
看下面一段代码:

cout << "后置++的参数运算" << endl;
for (i = 0; i < 10; i++)
{
cout <<"后置的i的值:" << i << ", "<<endl;
}
cout << endl;
for (i = 0;i < 10; ++i)
{
cout << "前置的i的值:" << i << ", "<<endl;
}
其运行结果图

两者运算的汇编代码如下图示:


两者的运算结果是一样的!查看其反汇编代码后,哦,原来两者的汇编代码是一样的!
(上述测试程序在VS2010和VS2019中测试的结果是一样的)
(完)

Tags:

最近发表
标签列表