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

C++:函数传参到函数执行结束发生了什么

首先要明确两个概念

  • 函数实参的入栈从右向左
  • 栈区从高地址向低地址偏移

接下来看下面一段代码

void fun(int a,int b,int c){std::cout<<&a<<" "<<&b<<" "<<&c<<std::endl;
}
int main(){fun(1,2,3);
}

这段代码看起来很简单但是你在不同环节下运行起来可能就会有问题了windows下vs
在这里插入图片描述
linux下vscode
在这里插入图片描述
可以看出一个是从左向右递增,一个是从左向右递减,你觉得这个是为什么呢?

我也不卖关子了,出现这种情况的原因是不同编译器将帧地址传递给函数后对函数局部变量的处理顺序不同。

函数从调用开始到结束过程

创建栈帧

在编译期编译器会根据类中局部变量的使用情况确定栈帧的大小

主函数帧指针
主函数内局部变量
返回地址
函数的帧指针(指向主函数帧指针)
函数的局部变量
栈指针

以上就是一个主函数调用一个函数时栈内的情况,栈帧可以理解为一个函数的活动空间,或者说运行环境,下面简述几个概念。

  • 帧指针:函数的主心骨,局部变量的创建都是在它的地址基础上偏移,它内部存函数调用者的帧指针地址
  • 栈指针,就是栈顶
  • 返回地址,存储调用函数完成后需要返回到的下一条指令的地址

栈帧的大小是在编译期间确定的,形参也处于局部变量的范畴,将实参从调用者的栈帧内移动到被调用者的栈帧内就涉及到了几种传参方式

  • 值传递
  • 址传递
  • 引用传递(也是通过址传递)

栈帧和代码区函数的交互

函数的运行在代码区,平时看汇编的时候如果你注意就会发现发生函数调用时一定会传一个东西,这个东西就是帧指针,比如下面这一坨

#include<iostream>
using namespace std;
void fun(){int nums[1024];
}int main() {fun();
}
fun():push    rbpmov     rbp, rspsub     rsp, 3976nopleaveret
main:push    rbpmov     rbp, rspcall    fun()mov     eax, 0pop     rbpret

这个rbp寄存器里面存的就是这个帧指针,sub rsp, 3976这个条指令就是进行栈指针的偏移,这个3976是栈帧内为局部变量预留的空间,至此可以说栈帧的创建完成了,接下来该使用了,局部变量的创建可以看到都是通过在rbp的基础上进行偏移的,需要注意的是编译器会进行各种优化你需要编译时加上-0o关闭优化,还有就是栈的对齐方式是16字节。

所以说当面试官问你栈区有没有产生内存碎片的可能时,你可以从容的回答栈的对齐大多数采用的是16字节可能会因为对齐方式而产生比较多的内存碎片,这些碎片显然是用不了的,高性能的代价往往是高内存消耗。

返回值的处理

一般来说对于返回值是函数的调用者需要关注的东西,现在的大部分编译器返回值的传递其实都是通过寄存器完成的,在不进行各种优化的情况下编译器会根据返回值的数据进行选择,如果数据量较大就使用寄存器返回地址,如果数据量较小则直接使用寄存器将结果返回,寄存器返回后会调用者的栈帧内拷贝一份函数的返回值,这个过程发生在函数栈帧被释放前,这个过程结合我之前的一篇文章:C++:完美转发和移动语义看会比较清楚。
上面那个过程显然不太合理,首先返回值不是被调用者需要考虑的东西,如果说我们直接在函数调用前在调用者的栈帧内创建好被调用者的返回值然后使用寄存器将这个地址传过去,在这个地址的基础上函数再进行处理不就行了吗?实际上这个就是RVO优化的原理,此外RVO还会判断返回值有没有被用到,如果没用的话也是会优化掉的。

RVO发生的条件通常是:在函数中创建了一个局部对象,并将其作为函数返回值,而调用方直接使用了这个返回值。在这种情况下,编译器可以直接将该局部对象放置到调用方期望的位置,而不需要进行复制或移动操作。

RVO失效情景

  • 返回多个对象: 如果函数返回多个对象,而不是一个单独的临时对象,那么RVO优化可能不适用。RVO通常仅适用于返回单个对象的情况
return pair<pair<int,int>,pair<int,int>>();
  • 虚函数调用: 当函数是虚函数时,编译器可能无法确定函数返回的对象的确切类型,从而阻止了RVO优化的应用
struct A{virtual A fun(){return *this;}};
struct B:public A{virtual B* fun(){return *this;}};
A* b=new B;
b->fun();
  • 复杂的返回逻辑
if(a) return a;
else if(b) return b;
return c;

观测RVO优化的过程,直接从上下文地址的变化非常直观

A get(){A a;cout<<&a<<endl;return a;
}int main() {A a;cout<<&a<<endl;a=get();A b;cout<<&b<<endl;
}

在这里插入图片描述
可以看到当发生RVO优化时会在调用者的栈帧内临时申请一块空间,生命周期过了就被下一个变量覆盖了,现在你应该对RVO和临时对象有了新的认识

总的来说,移动语义的引入可以说从根源上缓解了临时对象对程序性能的影响,就业务中可能出现的各种情况编译器可能不能很好的进行各种优化,所以合适的代码书写还是很有必要的,不要寄希望于各种优化了

栈帧的释放

返回值处理完成后,首先帧指针跳转到上一个节点然后栈指针向高地址偏移,直到遇到返回地址程序接着运行

回归到开头时候的问题,现在你大概已经直到答案了,没错就是不同操作系统在不同编译器下函数对参数的处理顺序不同造成的。

相关文章:

C++:函数传参到函数执行结束发生了什么

首先要明确两个概念 函数实参的入栈从右向左栈区从高地址向低地址偏移 接下来看下面一段代码 void fun(int a,int b,int c){std::cout<<&a<<" "<<&b<<" "<<&c<<std::endl; } int main(){fun(1,2,3); }…...

QT中dumpcpp以及dumpdoc使用

qt中调用COM的方式方法有四种&#xff0c;参考解释在 Qt 中使用 ActiveX 控件和 COM (runebook.dev) 介绍dumpcpp的使用方法Qt - dumpcpp 工具 (ActiveQt) (runebook.dev)&#xff1a; 在安装好了的qt电脑上&#xff0c;通过powershell窗口来实现&#xff0c;powershell比cmd要…...

RPM与DNF的操作实践

这几课有三个目标&#xff1a; 第一步&#xff1a;先配置软件源 跳转到yum.repos.d目录&#xff0c;用vim创建一个openeuler_x84_64.repo文件。这个文件就是我们将会用到的软件源。 我们在里面添加这些东西&#xff0c;保存并退出即可。 然后&#xff0c;我们用yum list all就…...

车道线检测之LaneNet

论文&#xff1a;Towards End-to-End Lane Detection: an Instance Segmentation Approach Github&#xff1a;https://github.com/MaybeShewill-CV/lanenet-lane-detection?tabreadme-ov-file 论文提出一种车道线检测网络LaneNet&#xff0c;该网络以enet为主干网络结构&…...

MySQL连接数不足导致服务异常GetConnectionTimeoutException

文章目录 场景复现解决方案一、调整连接数二、优化程序 场景复现 已经上线正常运行的项目突然很多功能无法使用&#xff0c;查看程序日志发现MySQL报错&#xff0c;异常信息: Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.Ge…...

软考76-上午题-【面向对象技术3-设计模式】-创建型设计模式01

一、创建型设计模式一览 二、创建型设计模式 2-1、创建型设计模式的概念 一个类创建型模式使用继承改变被实例化的类&#xff1b; 一个对象创建型模式将实例化委托给另一个对象。 对应java的new一个对象。 2-2、简单工厂模式&#xff08;静态工厂方法&#xff09; 简单工厂…...

Matlab 双目相机标定(内置函数)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 相机标定的目的就是要找到从世界坐标转换为图像坐标所用到的投影P矩阵各个系数(即相机的内参与外参)。具体过程如下所述: 1、首先我们需要获取一个已知图形的图像(这里我们使用MATLAB所提供的数据)。 2、找到同…...

【博客7.4】缤果Qt5_TWS串口调试助手V2.0 (高级篇)

超级好用的Qt5_TWS耳机串口调试助手 开发工具: qt-opensource-windows-x86-5.14.2 (编程语言C) 目录 前言 一、软件概要&#xff1a; 二、软件界面&#xff1a; 1.App演示 三、获取 >> 源码以及Git记录&#xff1a; 总结 前言 串口调试助手支持常用的50bps - 10M…...

CSS案例-4.padding导航栏练习

效果 相关数据: 上边框:3px,颜色#ff8500 下边框:1px,颜色#edeef0 背景颜色:#fcfcfc 高度:41px 内边距20px 字体颜色#4c4c4c 知识点 盒子边框border 属性 作用 border-width 定义边框粗细,单位px border-style 边框的样式 border-color 边框颜色 边框样式...

5.1.4.2、【AI技术新纪元:Spring AI解码】Llama2 Chat

Llama2 Chat Meta 的 Llama 2 Chat 是 Llama 2 系列大型语言模型的一部分。它在基于对话的应用程序中表现出色,参数规模范围从 70 亿到 700 亿不等。利用公共数据集和超过 100 万次人类注释,Llama Chat 提供了上下文感知的对话。 通过从公共数据源获取的 2 万亿标记进行训练…...

后台发送GET/POST方法

前言: 1,get请求 2,post请求 3,post,get通用方法 4,其他的get,post写法 正文: 1,get请求 import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; import or…...

计算机考研|双非一战135上岸,408经验分享+复盘

计算机专业的同学真的别想的太天真&#xff01; 相比于其他专业&#xff0c;计算机专业的同学其实还是很有优势的 但是现在随着计算机专业的同学越来越多&#xff0c;找工作的困难程度以及学历自然而然被卷起来了 以前的算法岗基本要求在本科以上&#xff0c;现在基本都是非92研…...

低代码与数字化工具:重塑软件开发的新范式

随着信息技术的飞速发展&#xff0c;软件开发已成为推动数字化转型的核心力量。在这个变革的时代&#xff0c;低代码与数字化工具逐渐崭露头角&#xff0c;它们不仅简化了开发过程&#xff0c;还大大提高了开发效率&#xff0c;成为推动软件开发领域变革的重要力量。 低代码&am…...

如何使用 ArcGIS Pro 生成TIN

三角网是一种常用于表示地表地形的数字地球模型&#xff08;DEM&#xff09;方式&#xff0c;我们可以通过 ArcGIS Pro 将等高线和高程点转换为TIN&#xff0c;这里为大家介绍一下转换方法&#xff0c;希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的高…...

你真的会做抖音小店吗?你做抖店的方法是正确的吗?教学分享

大家好&#xff0c;我是电商花花。 新的一年&#xff0c;不少做抖店的商家都会产生一个疑问&#xff0c;2024年抖音小店无货源还能继续做吗&#xff1f; 做无货源模式还会被处罚吗&#xff1f; 先说答案&#xff0c;2024年抖音小店无货源能做&#xff0c;不仅能做且仍然是抖音…...

ssh免密登陆更换目标主机后无法连接

在进行hadoop分布式环境搭建时&#xff08;三台机&#xff0c;master&#xff0c;slave1&#xff0c;slave2&#xff09;&#xff0c;后期slave2系统出现问题&#xff0c;更换新机后&#xff0c;master与slave2文件传输失败&#xff1a; 以为是秘钥过期的问题&#xff0c;更换…...

Java获取视频封面图,利用FFmpegFrameGrabber获取视频封面图

依赖 <dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.9</version></dependency>传入视频流获取图片byte /*** 获取视频截图** param frameNumber 视频的指定帧数* param …...

pycharm @NotNull parameter ‘module‘ of ...

下载了最新pycharm &#xff0c;无法启动运行 pycharm或者idea中Run/Debug Python项目报错 Argument for NotNull parameter ‘module‘ of … 解决方案 删除项目根目录的 idea 文件夹 随后重启&#xff0c;重新配置即可...

Python使用pynput模块后台监控鼠标及按键

Pynput 是一个 Python 第三方库&#xff0c;它提供了监听和控制键盘和鼠标事件的功能。使用 pynput&#xff0c;我们可以编写自动化脚本&#xff0c;监控输入设备的活动&#xff0c;或者实现一些与键盘和鼠标相关的功能。 一、功能说明 这段代码是运用pynput库实现对鼠标和键盘…...

C语言 扫雷游戏

写了这么长时间的关于C语言的基础知识&#xff0c;相信大家已经学会了使用C语言书写一些基础的代码&#xff0c;上次还编写了三子棋游戏的代码&#xff0c;这次我将编写一个基础版的扫雷游戏。 首先&#xff0c;创建三个文件&#xff0c;两个源文件&#xff0c;一个头文件&…...

HTML学习:图片格式——超链接

一、图片格式 1.jpg格式 概述:扩展名为.jpg 或.jpeg &#xff0c;是一种有损的压缩格式(把肉眼不容易观察出来的细节丢弃了)。 主要特点:支持的颜色丰富、占用空间较小、不支持透明背景、不支持动态图。 使用场景:对图片细节没有极高要求的场景&#xff0c;例如:网站的产品…...

工业级5g路由器使用案例(5g智慧安防解决方案)

​项目背景: 现代化智慧安防需要满足远程可视化监控、设备联网管理、数据加密传输等多重需求,对通信网络的带宽、时延、安全性等提出了很高要求。业内急需一款高可靠、高性能、易管理的通信网关设备,来确保安防系统的顺利运行。 安装部署: SR800-D路由器采用紧凑型全金属机箱…...

sentinel熔断降级

熔断降级 Slot 责任链上的最后一环&#xff1a;熔断降级 DegradeSlot,熔断降级作为保护系统的一种强大手段,可以根据慢调用、异常比例和异常数进行熔断,并自定义持续时间以实现系统保护 规则配置 规则类中属性解析 与控制面板对应 // 其中资源名称在 AbstractRule 里。 pu…...

Redis的安装和部署教程(Windows环境)

一、安装Redis服务 1、下载Redis压缩包 以下这个是我网盘里面的&#xff08;这个是v8.0版本的&#xff0c;支持导入.rdb数据文件&#xff09; 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;x0f1 --来自百度网盘超级会员V5的分享 2、解压到文件夹 将下载的压缩…...

MNN Session::resize 之流水线编码(五)

系列文章目录 MNN createFromBuffer&#xff08;一&#xff09; MNN createRuntime&#xff08;二&#xff09; MNN createSession 之 Schedule&#xff08;三&#xff09; MNN createSession 之创建流水线后端&#xff08;四&#xff09; MNN Session::resize 之流水线编码&am…...

2. IS-IS 基础实验

2.1 IS-IS 配置实验 2.1.1 实验介绍 2.1.1.1 学习目标 1. 实现 IS-IS 协议基本配置 2. 实现 IS-IS 协议 DIS 优先级修改 3. 实现 IS-IS 协议网络类型修改 4. 实现 IS-IS 协议外部路由引入 5. 实现 IS-IS 接口 cost 修改 6. 实现 IS-IS 路由渗透配置 2.1.1.2 实验组网介…...

Rust 并行库 crossbeam 的 Channel 示例

示例1 一个不完整的示例&#xff1a; let (tx, rx) channel::unbounded::<Task>(); let mut handlers vec![];for _ in 0..number {let rx rx.clone();let handle thread::spawn(move || {while let Some(task) rx.recv() {task.call_box();}});handlers.push(han…...

缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级的理解

一&#xff1a;缓存雪崩 我们可以简单的理解为&#xff1a;由于原有缓存失效&#xff0c;新缓存未到期间 (例如&#xff1a;我们设置缓存时采用了相同的过期时间&#xff0c;在同一时刻出现大面积的缓存过期)&#xff0c;所有原本应该访问缓存的请求都去查询数据库了&#xff…...

springcloud gateway

一、 predicate : 就是你定义一些规则&#xff0c;如果满足了这些规则&#xff0c;就去找到对应的路由。 对于strip 二、自定义过略器和全局过滤器 约定大于配置&#xff0c;后缀不变&#xff0c;只改前缀 sentinel持久化 三、sentinel quick-start | Sentinel 信号量虽然简…...

JAVA八股day1

遇到的问题 相比于包装类型&#xff08;对象类型&#xff09;&#xff0c; 基本数据类型占用的空间往往非常小为什么说是几乎所有对象实例都存在于堆中呢&#xff1f;静态变量和成员变量、成员变量和局部变量的区别为什么浮点数运算的时候会有精度丢失的风险&#xff1f;如何解…...

广州公司建设网站/做网络推广怎么收费

为什么其他人都是插值套插值啊&#xff0c;&#xff0c;&#xff0c;&#xff0c;就我是XJB做的吗2333 k次多项式的前缀和可以表示成k1次多项式&#xff0c;用两次这个玩意就可以发现g可以表示成一个k2次多项式。 然后我的做法是把g用拉格朗日插值暴力多项式乘法乘出来&#xf…...

什么更新wordpress/十大计算机培训学校

grep&#xff1a;文本过滤器 能够根据指定的模式去查找匹配到模式的行&#xff0c;并将相应的行显示出来。 sed&#xff1a;流编辑器 默认的编辑结果不会保存到原文件当中而是输出到屏幕上。 一、awk&#xff1a;报告生成器 从文本文件当中抽取符合条件的信息&#xff0c;并以特…...

wordpress内容页文字红色/公司企业网站制作

键盘小钢琴[C语言][自制]大一上最喜欢的一个作品。刚开始只是一个能自动发出小星星音乐的小程序XD效果图&#xff1a;代码如下&#xff1a;/*This is a small piano.这是一个小钢琴哦~*/#include#include //非缓冲输入#include#include#pragma warning(disable:4996) //to use …...

做内网网站/seo去哪里学

基于计算机视觉技术的入侵检测通过设计图像处理方法实现对某一动态场景的实时观测&#xff0c;并在场景存在外来入侵情况时向上层管理系统发送入侵检测结果&#xff1b;要求独立编写具有以下功能模块的程序源码&#xff0c; 1&#xff0e; 通过手机/个人笔记本内置摄像机连续…...

可视化前端开发工具/一点优化

智慧农业IOT-onenet平台简单介绍 1、onenet平台简介 1.1、 onenet简介 ​ OneNET是由中国移动打造的PaaS物联网开放平台。平台能够帮助开发者轻松实现设备接入与设备连接&#xff0c;快速完成产品开发部署&#xff0c;为智能硬件、智能家居产品提供完善的物联网解决方案。是…...

网站克隆下来了然后再怎么做/河南网站推广那家好

一、填空题1&#xff0e; 对于一个具有n 个结点的单链表&#xff0c;在已知的结点半p 后插入一个新结点的时间. 复杂度为_____&#xff0c;在给定值为x 的结点后插入一个新结点的时间复杂度为_____。【答案】【解析】第一种情况只需直接修改指针的指向。第二种情况必须从头结点…...