为什么说 i的效率比i 高?
创始人
2025-03-18 01:21:54
0次

不知道你是否听说过++i比i++快的说法,真的如此吗?

++i与i++的区别

这两个表达式从我们初学编程语言的时候就会接触到。前者是自增后取值,后者是取值后自增。

我们看一个简单的例子。

  1. #include  
  2. using namespace std; 
  3. int main() 
  4. { 
  5.     int a = 0; 
  6.     int b = 0; 
  7.     int c = a++;//int tmp = a;c=a;aa = a + 1 
  8.     int d = ++b;//bb = b + 1;d = b; 
  9.     cout<<"c="<
  10.     return 0; 
  11. } 

运行结果:

  1. c=0;d=1   

对于这个结果我们并不感到意外。

另外我们还注意到另外一个有意思的现象:

  1. #include  
  2. using namespace std; 
  3. int main() 
  4. { 
  5.     int a = 0; 
  6.     int b = 0; 
  7.     int *c = &(a++); 
  8.     int *d = &(++b); 
  9.     return 0; 
  10. } 

编译后报错:

  1. main.cpp:7:19: error: lvalue required as unary ‘&’ operand 
  2.      int *c = &(a++); 

说&作用于左值,也就是说a++的结果并非左值。但++b的结果是左值。

可简单理解左值和右值:

  • 左值,有名对象,可赋值
  • 右值,临时对象,不可被赋值

运算符重载

通过前面的例子也发现了,对于内置类型,前置自增返回对象的引用,而后置自增返回对象的原值(但非左值)。

基于上述原则,一个前置版本和后置版本的常见实现如下:

  1. class Test 
  2. { 
  3. public: 
  4.     Test& operator++();//前置自增 
  5.     const Test operator++(int);//后置自增 
  6. private: 
  7.     int curPos; //当前位置 
  8. }; 
  9. /*前置自增实现范式*/ 
  10. Test& Test::operator++() 
  11. { 
  12.     ++curPos;      //自增 
  13.     return *this;  //取值 
  14. } 
  15. /*后置自增实现范式,为了与前置区分开,多了一个int参数,但从来没用过*/ 
  16. const Test Test::operator++(int) 
  17. { 
  18.     Test tmp = *this;  //取值 
  19.     ++curPos;             //自增 
  20.     return tmp; 
  21. } 

仔细观察后,我们发现前置自增,先自增,后返回原对象的对象;没有产生任何临时对象;而后置自增,先保存原对象,然后自增,最后返回该原临时对象,那么它就需要创建和销毁,这样一来,效率孰高孰低就很清楚了。

在不进行赋值的情况下,内置类型前置和后置自增的汇编都是一样的呢!

  1. void test() 
  2. { 
  3.   int i = 0; 
  4.   i++; 
  5.   //++i; 
  6. } 

汇编:

  1. push    rbp 
  2. mov     rbp, rsp 
  3. mov     DWORD PTR [rbp-4], 0 
  4. add     DWORD PTR [rbp-4], 1 
  5. nop 
  6. pop     rbp 
  7. ret 

不过,赋值的情况下,并且不开启编译器优化,它们的汇编代码还是有差别的,有兴趣的可以试试。

总结

对于内置类型,前置和后置自增或者自减在编译器优化的情况下,两者并无多大差别,而对于自定义类型,如无特别需要,人们似乎更加偏爱前置自增或自减,因为后置自增常常会产生临时对象。

但是,又能提高多少效率呢?

 

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
只需三步,让你掌握阿尔法路由器... 请参照以下阿尔法路由器设置方法,通过浏览器进入及设置宽带路由器。经过这三个步骤的设置,基本上能够熟悉...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
30分钟搞定iOS自定义相机 最近公司的项目中用到了相机,由于不用系统的相机,UI给的相机切图,必须自定义才可以。就花时间简单研究...