当前位置: 首页 > 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++还是会报无法对右值取地址,其实也是编译器对这种复杂点的语句,不会对前置自增后置自增进行优化,生成汇编代码的时候还是对右值取的地址,导致的报错。

相关文章:

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

简介 先说i和i的区别&#xff0c;判断语句中if(i)是拿i的值先判断&#xff0c;而后自增&#xff1b;if(i)是先自增i再进行判断。涉及到左值与右值也有点区别&#xff0c;i返回的是右值&#xff0c;i返回的是左值。也就是下面的代码要解释的东西。 #include <iostream>i…...

实战打靶集锦-005-HL

**写在前面&#xff1a;**记录一次曲折的打靶经历。 目录1. 主机发现2. 端口扫描3. 服务枚举4. 服务探查4.1 浏览器访问4.2 目录枚举4.3 探查admin4.4 探查index4.5 探查login5 公共EXP搜索6. 再次目录枚举6.1 探查superadmin.php6.2 查看页面源代码6.3 base64绕过6.4 构建反弹…...

铁路系统各专业介绍(车机工电辆)

目录 1 车务段 1.1 职能简介 1.2 路段名单 1.3 岗位级别 2 机务段 2.1 职能简介 2.2 路段名单 2.3 岗位级别 3 工务段 3.1 职能简介 3.2 路段名单 3.3 岗位级别 4 电务段 4.1 职能简介 4.2 路段名单 4.3 岗位级别 5 车辆段 5.1 职能简介 5.2 路段名单 5.3 …...

2/11考试总结

时间安排 7:30–7:50 读题&#xff0c;T1貌似是个 dp &#xff0c;T2 数据结构&#xff0c;T3 可能是数据结构。 7:50–9:45 T1&#xff0c;点规模非常大&#xff0c;可以达到 1e18 级别&#xff0c;感觉应该没法直接做&#xff0c;考虑每条新增的边的贡献&#xff0c;想到用 …...

Java Set集合

7 Set集合 7.1 Set集合的概述和特点 Set集合的特点 不包含重复元素的集合没有带索引的方法&#xff0c;所以不能使用普通for循环 Set集合是接口通过实现类实例化&#xff08;多态的形式&#xff09; HashSet&#xff1a;添加的元素是无序&#xff0c;不重复&#xff0c;无索引…...

【手写 Vuex 源码】第七篇 - Vuex 的模块安装

一&#xff0c;前言 上一篇&#xff0c;主要介绍了 Vuex 模块收集的实现&#xff0c;主要涉及以下几个点&#xff1a; Vuex 模块的概念&#xff1b;Vuex 模块和命名空间的使用&#xff1b;Vuex 模块收集的实现-构建“模块树”&#xff1b; 本篇&#xff0c;继续介绍 Vuex 模…...

EOC第六章《块与中枢派发》

文章目录第37条&#xff1a;理解block这一概念第38条&#xff1a;为常用的块类型创建typedef第39条&#xff1a;用handler块降低代码分散程度第41条&#xff1a;多用派发队列&#xff0c;少用同步锁方案一&#xff1a;使用串行同步队列来将读写操作都安排到同一个队列里&#x…...

八、Git远程仓库操作——跨团队成员的协作

前言 前面一篇博文介绍了git团队成员之间的协作&#xff0c;现在在介绍下如果是跨团队成员的话&#xff0c;如何协作&#xff1f; 跨团队成员协作&#xff0c;其实就是你不属于那个项目的成员&#xff0c;你没有权限向那个仓库提交代码。但是github还有另一种 pull request&a…...

算法刷题打卡第88天:字母板上的路径

字母板上的路径 难度&#xff1a;中等 我们从一块字母板上的位置 (0, 0) 出发&#xff0c;该坐标对应的字符为 board[0][0]。 在本题里&#xff0c;字母板为board ["abcde", "fghij", "klmno", "pqrst", "uvwxy", "…...

UVa The Morning after Halloween 万圣节后的早晨 双向BFS

题目链接&#xff1a;The Morning after Halloween 题目描述&#xff1a; 给定一个二维矩阵&#xff0c;图中有障碍物和字母&#xff0c;你需要把小写字母移动到对应的大写字母位置&#xff0c;不同的小写字母可以同时移动&#xff08;上下左右四个方向或者保持不动 &#xff0…...

Connext DDS属性配置参考大全(3)

Transport传输dds.participant.logging.time_based_logging.process_received_messagedds.participant.logging.time_based_logging.process_received_message.timeout...

Docker-安装Jenkins-使用jenkins发版Java项目

文章目录0.前言环境背景1.操作流程1.1前期准备工作1.1.1环境变量的配置1.2使用流水线的方式进行发版1.2.1新建流水线任务1.2.2流水线操作工具tools步骤stages步骤1:拉取代码编译步骤2:发送文件并启动0.前言 学海无涯&#xff0c;旅“途”漫漫&#xff0c;“途”中小记&#xff…...

spring 中的 Bean 是否线程安全

文章目录结论1、spring中的Bean从哪里来&#xff1f;2、spring中什么样的Bean存在线程安全问题&#xff1f;3、如何处理spring Bean的线程安全问题&#xff1f;结论 其实&#xff0c;Spring 中的 Bean 是否线程安全&#xff0c;其实跟 Spring 容器本身无关。Spring框架中没有提…...

微电网两阶段鲁棒优化经济调度方法[3]【升级优化版本】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑…...

C++入门教程||C++ 数据类型||C++ 变量类型

C 数据类型 使用编程语言进行编程时&#xff0c;需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着&#xff0c;当您创建一个变量时&#xff0c;就会在内存中保留一些空间。 您可能需要存储各种数据类型&#xff08;比如字符型、宽字符型、整型…...

【visio使用技巧】图片导出pdf时去掉多余空白

问题 在visio导出pdf格式的图片时&#xff0c;往往会存在多余的白边&#xff0c;如下图所示&#xff1a; 解决方法 依次点击&#xff1a;菜单栏→文件→选项→自定义功能区→勾选“开发工具”→确定。 依次点击菜单栏→开发工具→显示ShapeSheet→页→Print Properties→将…...

Rust语言之Option枚举类型

概述 Option是Rust语言设计中最重要的枚举类型之一&#xff0c;它编码了其它语言中空值与非空值的概念&#xff0c;差异在于&#xff0c;Rust不会允许你像其它语言一样以非空值的方式来使用一个空值&#xff0c;这避免了很多错误。Option在标准库中的定义如下&#xff1a; pu…...

基于TimeQuest时序优化原理和方法

&#x1f4a1; 回顾基于RTL逻辑时序优化的基本思路&#xff0c;在关键路径中插入寄存器来优化时序 分析最坏路径 通过前面对TimeQuest软件的理解&#xff0c;基本上可以找到关键路径&#xff0c;此文章主要对关键路径时序进行优化&#xff0c;使设计达到时序要求&#xff0c;以…...

LeetCode第332场周赛

2023.2.12LeetCode第332场周赛 6354. 找出数组的串联值 思路 双指针模拟&#xff0c;两个指针相遇的时候要特判 算法 class Solution { public:long long findTheArrayConcVal(vector<int>& nums) {long long ans 0;int i 0, j nums.size() - 1;while (i <…...

2023-2-12刷题情况

字母板上的路径 题目描述 我们从一块字母板上的位置 (0, 0) 出发&#xff0c;该坐标对应的字符为 board[0][0]。 在本题里&#xff0c;字母板为board [“abcde”, “fghij”, “klmno”, “pqrst”, “uvwxy”, “z”]&#xff0c;如下所示。 我们可以按下面的指令规则行动…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...

【WebSocket】SpringBoot项目中使用WebSocket

1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖&#xff0c;添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...