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

news2024/12/28 18:49:53

首先要明确两个概念

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

接下来看下面一段代码

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    rbp
        mov     rbp, rsp
        sub     rsp, 3976
        nop
        leave
        ret
main:
        push    rbp
        mov     rbp, rsp
        call    fun()
        mov     eax, 0
        pop     rbp
        ret

这个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和临时对象有了新的认识

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

栈帧的释放

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1520739.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最全集装箱知识汇总详解!

1、大柜、小柜、双背是指&#xff1f; 集装箱有不同的尺寸和搭配方式&#xff0c;大柜、小柜、双背就是其中的一些常见的分类。具体来说&#xff1a; 大柜是指长度为40英尺的集装箱&#xff0c;一般有40GP和40HQ两种类型。45英尺的集装箱比较特殊&#xff0c;不算大柜。 小柜…

10.用AI解释AI

文章目录 用AI解释AI目的思路成功解释实例失败例子 评估解释结果结果分析方法小结整体评估缺点与改进其他槽点 部分截图来自原课程视频《2023李宏毅最新生成式AI教程》&#xff0c;B站自行搜索。 用AI解释AI来自openAI的论文&#xff1a; Language models can explainneurons …

凝思操作系统离线安装mysql和node

PS&#xff1a;下面这就是国产凝思的界面,测试版本是V6.0.80&#xff0c;第一次听说这种系统&#xff0c;于是去官网下载部署包&#xff0c;下面是地址 注意:这个系统如果没有激活&#xff0c;ip都不会有&#xff0c;这样文件都不能传到服务器&#xff0c;xshell这些工具都连不…

java-ssm-jsp基于java的信访管理系统的设计与实现

java-ssm-jsp基于java的信访管理系统的设计与实现 获取源码——》公主号&#xff1a;计算机专业毕设大全 获取源码——》公主号&#xff1a;计算机专业毕设大全

双线性插值缩放算法原理以及matlab与verilog的实现(二)

系列文章目录 双线性插值缩放算法原理以及matlab与verilog的实现&#xff08;一&#xff09; 文章目录 系列文章目录前言一、前提回顾二、FPGA实现步骤2.1 找到源图像四个像素点求目标像素点2.2 FPGA实现步骤2.3 总体框架2.4 ROM缓存模块2.5 VGA模块2.6 双线性算法模块 三、下…

《Learning Hierarchical Modular Networks for Video Captioning》论文笔记

论文信息 原文链接&#xff1a; Learning Hierarchical Modular Networks for Video Captioning | IEEE Journals & Magazine | IEEE Xplore 原文代码 GitHub - MarcusNerva/HMN: [CVPR2022] Official code for Hierarchical Modular Network for Video Captioning. Ou…

C#,图论与图算法,双连通图(Biconnected Components of Graph)的算法与源代码

1 双连通图(Biconnected Components of Graph) 如果任意两个顶点之间有两条顶点不相交的路径,则无向图称为双连通图。在双连通图中,有一个通过任意两个顶点的简单循环。 按照约定,由边连接的两个节点构成双连通图,但这并不验证上述属性。对于具有两个以上顶点的图,必须…

原生微信小程序代码转uniapp代码 插件

一、安装依赖 npm install miniprogram-to-uniapp -g 继续在命令行里&#xff0c;运行【 wtu -V 】&#xff0c;查看版本号&#xff0c;执行结果如下&#xff1a; 二、使用插件 wtu -i "这里写你的微信小程序项目路径" 如&#xff1a;【wtu -i "D:\Desktop\…

【PyTorch】基础学习:在Pycharm等IDE中打印或查看Pytorch版本信息

【PyTorch】基础学习&#xff1a;在Pycharm等IDE中打印或查看Pytorch版本信息 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1…

【C++】实现红黑树

目录 一、认识红黑树1.1 概念1.2 定义 二、实现红黑树2.1 插入2.2 与AVL树对比 一、认识红黑树 1.1 概念 红黑树是一个二叉搜索树&#xff0c;与AVL树相比&#xff0c;红黑树不再使用平衡因子来控制树的左右子树高度差&#xff0c;而是用颜色来控制平衡&#xff0c;颜色为红色…

52 硬中断的实现

前言 呵呵 中断机制 也是内核中很常见的机制了 中断机制是现代计算机系统中的基本机制之一&#xff0c;它在系统中起着通信网络的作用&#xff0c;以协调系统对各种外部事件的响应和处理&#xff0c;中断是实现多道程序设计的必要条件&#xff0c;中断是CPU 对系统发生的某个…

C#,入门教程(27)——应用程序(Application)的基础知识

上一篇: C#,入门教程(26)——数据的基本概念与使用方法https://blog.csdn.net/beijinghorn/article/details/124952589 一、什么是应用程序 Application? 应用程序是编程的结果。一般把代码经过编译(等)过程,最终形成的可执行 或 可再用 的文件称为应用程序。可执行文…

cool 中的Midway ----node.js的TypeORM的使用

1.介绍 TypeORM | Midway TypeORM 是 node.js 现有社区最成熟的对象关系映射器&#xff08;ORM &#xff09;。本文介绍如何在 Midway 中使用 TypeORM 相关信息&#xff1a; 描述可用于标准项目✅可用于 Serverless✅可用于一体化✅包含独立主框架❌包含独立日志❌ 和老写…

Docker入门一(Docker介绍、Docker整体结构、Docker安装、镜像、容器、Docker的容器与镜像)

文章目录 一、Docker介绍1.什么是虚拟化2.虚拟化模块3.docker是什么4.docker平台介绍5.为什么使用docker6.docker主要解决的问题 二、docker整体结构1.Docker引擎介绍&#xff08;Docker Engine&#xff09;2.Docker结构概览介绍3.Docker底层技术 三、docker安装1.Docker-CE和D…

【java开发者工具】IDEA(java编程语言开发的集成环境)带你了解背后故事与基础操作指南

✅作者简介&#xff1a;大家好&#xff0c;我是橘橙黄又青&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;橘橙黄又青-CSDN博客 1.&#x1f34e; IDEA介绍 IDEA 全称 IntelliJ IDEA&#xff0c;是java编程语言的集成开…

202109青少年软件编程(图形化) 等级考试试卷(二级)

第1题:【 单选题】 执行下图所示程序, 舞台上的角色?( ) A:在 1 秒内滑行到随机位置 B:不断地重复滑行到随机位置 C:只有按下空格键的时候, 才会滑行到随机位置 D:只有按下空格键以外键的时候, 才会滑行到随机位置 【正确答案】: C 【试题解析】 : 第2题:【 单…

力扣简单串题:转换成小写字母

char* toLowerCase(char* s) {if(sNULL){return NULL;}for(int x0;x<strlen(s);x){if(s[x]>A&&s[x]<Z){s[x]s[x]-Aa;}}return s; }

高速电路顶级会议DesignCon 2021年会议总结和论文资料分享

DesignCon2021基本介绍 DesignCon 2021是一个涉及设计、创新和技术的年度会议&#xff0c;于2021年在美国加利福尼亚州举行。以下是该会议的一些重要主题和亮点&#xff1a; 人工智能和机器学习&#xff1a;会议探讨了人工智能和机器学习如何改变设计过程&#xff0c;以及设计…

二,几何相交---4,BO算法---(3)数据结构

数据结构分两块&#xff0c;一个是某一时间状态的局部相交线段。一个是事件队列&#xff0c;是某一时刻局部相交线段的集合。

WRF模型运行教程(ububtu系统)--III.运行WRF模型(官网案例)

零、创建DATA目录 # 1.创建一个DATA目录用于存放数据&#xff08;一般为fnl数据&#xff0c;放在Build_WRF目录下&#xff09;。 mkdir DATA # 2.进入 DATA cd DATA 一、WPS预处理 在模拟之前先确定模拟域&#xff08;即模拟范围&#xff09;,并进行数据预处理&#xff08…