当前位置: 首页 > news >正文

【C++奇技淫巧】前置自增与后置自增的区别(++i,i++)【2023.02.08】

简介

先说++ii++的区别,判断语句中if(i++)是拿i的值先判断,而后自增;if(++i)是先自增i再进行判断。涉及到左值与右值也有点区别,i++返回的是右值,++i返回的是左值。也就是下面的代码要解释的东西。

#include <iostream>int main()
{//后置自增,返回右值int i = 0;auto pi = &(i++); 错误 右值无法取地址//前置自增,返回左值int j = 0;auto pj = &(++j);// 正确std::cout << "Hello World!\n";
}

转折

老生常谈的经验是++ii++性能好,因为++i中间会产生临时变量,参考这篇文章的解释http://t.csdn.cn/2A7PT。实际上较新的编译器,简单的自增没有差别了。我们看下汇编代码:

int i = 0;
00007FF73AD21C9B  mov         dword ptr [i],0  i++;
00007FF73AD21CA2  mov         eax,dword ptr [i]  
00007FF73AD21CA5  inc         eax  
00007FF73AD21CA7  mov         dword ptr [i],eax  int j = 0;
00007FF73AD21CAA  mov         dword ptr [j],0  ++j;
00007FF73AD21CB1  mov         eax,dword ptr [j]  
00007FF73AD21CB4  inc         eax  
00007FF73AD21CB6  mov         dword ptr [j],eax  

i++++j的汇编代码一模一样,基本不涉及临时变量。

我们加上if进行观察:

    int i = 0;
00007FF7BEB91C9B  mov         dword ptr [i],0  if (i++)
00007FF7BEB91CA2  mov         eax,dword ptr [i]  
00007FF7BEB91CA5  mov         dword ptr [rbp+0F4h],eax  
00007FF7BEB91CAB  mov         eax,dword ptr [i]  
00007FF7BEB91CAE  inc         eax  
00007FF7BEB91CB0  mov         dword ptr [i],eax  {}//前置自增,返回左值int j = 0;
00007FF7BEB91CB3  mov         dword ptr [j],0  if (++j)
00007FF7BEB91CBA  mov         eax,dword ptr [j]  
00007FF7BEB91CBD  inc         eax  
00007FF7BEB91CBF  mov         dword ptr [j],eax  {}

注意:00007FF7BEB91CA5 mov dword ptr [rbp+0F4h],eax 这行代码是把i++前的值拷贝到临时变量了,临时变量的地址是rbp+0F4h。而后才对i进行自增操作。

总结

也就是说编译器优化仅对简单的自增进行了优化,但是复杂的,甚至仅仅是套了一层if,编译器是不会优化的,因为要兼容已有的代码。如果if里面的也做优化,则之前那么多的程序岂不是要炸了💣?也就是语义上要保持连贯性,已经形成共识的东西编译器是会传承下去的。

再一个也是不理解既然汇编语言i++++i都一样,为什么&i++还是会报无法对右值取地址,其实也是编译器对这种复杂点的语句,不会对前置自增后置自增进行优化,生成汇编代码的时候还是对右值取的地址,导致的报错。

http://www.lryc.cn/news/4505.html

相关文章:

  • 实战打靶集锦-005-HL
  • 铁路系统各专业介绍(车机工电辆)
  • 2/11考试总结
  • Java Set集合
  • 【手写 Vuex 源码】第七篇 - Vuex 的模块安装
  • EOC第六章《块与中枢派发》
  • 八、Git远程仓库操作——跨团队成员的协作
  • 算法刷题打卡第88天:字母板上的路径
  • UVa The Morning after Halloween 万圣节后的早晨 双向BFS
  • Connext DDS属性配置参考大全(3)
  • Docker-安装Jenkins-使用jenkins发版Java项目
  • spring 中的 Bean 是否线程安全
  • 微电网两阶段鲁棒优化经济调度方法[3]【升级优化版本】(Matlab代码实现)
  • C++入门教程||C++ 数据类型||C++ 变量类型
  • 【visio使用技巧】图片导出pdf时去掉多余空白
  • Rust语言之Option枚举类型
  • 基于TimeQuest时序优化原理和方法
  • LeetCode第332场周赛
  • 2023-2-12刷题情况
  • 拉普拉斯矩阵
  • Top-1错误率、Top-5错误率等常见的模型算法评估指标解析
  • Urho3D 容器类型
  • C语言学习笔记(四): 循环结构程序设计
  • 02 OpenCV图像通道处理
  • 微信小程序图书馆座位预约管理系统
  • 有限元分析学习一
  • android avb2.0 总结
  • 聊天机器人-意图识别类,开源库推荐
  • Java 标识符以及修饰符
  • 封装、继承、Super、重写、多态instanceof类型转换的使用以及个人见解