(C++)i++和++i,哪个效率高一些

本文探讨了C++中前置递增(++i)与后置递增(i++)的区别,通过高级语言层面及底层汇编代码对比分析了两者在内置类型和自定义类型上的效率差异。

链接:http://www.cnblogs.com/AndyJee/p/4550391.html

在看《程序员面试笔试宝典》时,发现了这样一个问题,书中只给出了++i的效率高一些,但并没有给出具体的解释和说明。

在网上找到下面的答案:

1、从高级层面上解释

++i 是i=i+1,表达式的值就是i本身

i++ 也是i=i+1,但表达式的值是加1前的副本,由于要先保存副本,因此效率低一些。

对于C++内置类型而言,大部分编译器会做优化,因此效率没什么区别。但在自定义类型上,就未必有优化,++i 效率会高一些。

2、从底层汇编来看内置类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int  a,i=0; a=++i;汇编代码如下:
 
int  a,i=0;
01221A4E mov dword ptr [i],0
a=++i;
01221A55 mov eax,dword ptr [i]
01221A58 add eax,1
01221A5B mov dword ptr [i],eax
01221A5E mov ecx,dword ptr [i]
01221A61 mov dword ptr [a],ecx
 
int  a,i=0; a=i++;汇编代码如下:
 
int  a,i=0;
009E1A4E mov dword ptr [i],0
a=i++;
009E1A55 mov eax,dword ptr [i]
009E1A58 mov dword ptr [a],eax
009E1A5B mov ecx,dword ptr [i]
009E1A5E add ecx,1
009E1A61 mov dword ptr [i],ecx

从上述汇编代码可以看到,对于内置类型,它们的执行数目是一样的,效率没有差别。

3、从重载运算符来看自定义类型

1
2
3
4
5
6
7
8
9
10
11
12
13
Operator Operator:: operator ++()
{
++value;  //内部成员变量
return  * this ;
}
 
Operator Operator:: operator ++( int )
{
Operator temp;
temp.value=value;
value++;
return  temp;
}

从上面代码可以看出,后置++多了一个保存临时对象的操作,因此效率自然低一些。

总结:

对于C++内置类型,两者的效率差别不大;

对于自定义的类而言,++i 的效率更高一些。

 

参考文章:

http://www.cplusplus.me/1303.html

C++中,前置自增运算符(++I)后置自增运算符(I++)都用于将变量的值增加1,但它们在使用方式底层实现上存在一些区别。 ### 基本使用区别 在判断语句中,二者表现不同。使用后置自增运算符(I++)时,会先使用变量I的当前值进行判断,然后再将I的值加1;而使用前置自增运算符(++I)时,会先将I的值加1,然后再使用增加后的值进行判断。示例代码如下: ```cpp #include <iostream> int main() { int i = 0; if (i++) { std::cout << "This won't be printed because i was 0 initially." << std::endl; } std::cout << "After i++, i is: " << i << std::endl; int j = 0; if (++j) { std::cout << "This will be printed because j is now 1." << std::endl; } std::cout << "After ++j, j is: " << j << std::endl; return 0; } ``` ### 左值与右值区别 后置自增运算符(I++)返回的是右值,而前置自增运算符(++I)返回的是左值。右值不能取地址,左值可以取地址。示例代码如下: ```cpp #include <iostream> int main() { int i = 0; // auto pi = &(i++); // 错误,右值无法取地址 int j = 0; auto pj = &(++j); // 正确 std::cout << "Address of j after ++j: " << pj << std::endl; return 0; } ``` ### 效率区别 前置自增运算符(++I)通常要比后置自增运算符(I++)效率更高。后置自增运算符的底层实现在递增之前需要创建元素的拷贝,然后返回该拷贝;而前置自增运算符直接对原对象进行操作并返回原对象的引用。示例代码如下: ```cpp #include <iostream> class MyInteger { friend std::ostream& operator<<(std::ostream& out, MyInteger myint); public: MyInteger() { m_Num = 0; } // 前置++ MyInteger& operator++() { m_Num++; return *this; } // 后置++ MyInteger operator++(int) { MyInteger temp = *this; m_Num++; return temp; } private: int m_Num; }; std::ostream& operator<<(std::ostream& out, MyInteger myint) { out << myint.m_Num; return out; } int main() { MyInteger myInt; std::cout << ++myInt << std::endl; // 前置++ MyInteger anotherInt; std::cout << anotherInt++ << std::endl; // 后置++ return 0; } ``` ### 优先级区别 依照运算符的“贪心律”,后缀运算符优先级是最高的。例如对于表达式`(b++)+a`,由于后缀运算符优先级高,所以会先计算`b++`,而不是`++a` [^4]。 ### 左值使用区别 后置自增表达式不能作为左值使用,而前置自增表达式可以。例如`(a++)++`、`++(a++)`、`a++ = 1` 会编译错误;而`(++a)++`、`++(++a)`、`++a = 1` 是合法的 [^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值