C++ 学习系列3 -- 函数压栈与出栈

在C++中,函数压栈(函数调用)和出栈(函数返回)是函数调用过程中的两个关键步骤。下面将逐步解释这两个过程:

一  函数压栈与出栈过程简介

函数压栈(函数调用)的过程如下:

  1. 调用指令:在函数调用点,会发出一个调用指令(如call指令),将控制权转移到被调用函数的入口点。
  2. 保存返回地址:调用指令执行前,当前函数的返回地址会被压入栈中,以便在函数执行完毕后返回到正确的位置。
  3. 参数压栈:函数调用时,将函数的参数按照一定的顺序压入栈中。通常,参数从右至左依次入栈。
  4. 保存寄存器值:在一些体系结构中,函数调用时需要保存一些寄存器的值,以便在函数执行完毕后能够恢复原始的寄存器状态。
  5. 帧指针与局部变量压栈:为了支持函数内的局部变量和堆栈的动态分配,通常会在栈上维护一个帧指针(frame pointer),它指向当前函数的栈帧(stack frame)的底部。同时,函数内部定义的局部变量也会在栈上分配空间。
  6. 执行函数体:一旦函数的参数、局部变量和其他上下文信息都被压入栈中,函数体中的代码开始执行。

函数出栈(函数返回)的过程如下:

  1. 恢复寄存器值:在一些体系结构中,函数返回时需要恢复之前保存的寄存器的值。
  2. 释放局部变量和帧指针:函数返回后,会释放函数内部定义的局部变量所占用的栈空间,并将帧指针恢复到上一层函数的栈帧。
  3. 弹出参数和返回地址:函数返回后,参数和返回地址会从栈中弹出,将控制权返回到调用函数的正确位置。

二 参数入栈顺序

c/c++中规定了函数参数的压栈顺序是从右至左

可以看如下例子:

// person.h
#include<string>class Person
{
public:Person(std::string name);Person(const Person& p);~Person();private:std::string m_name;
};//------------------------// person.cpp#include "person.h"
#include<iostream>
Person::Person(std::string name):m_name(name)
{std::cout << "Person constructor name: " << m_name << std::endl;
}Person::~Person()
{std::cout << "Person destructor name: " << m_name << std::endl;
}Person::Person(const Person& p)
{this->m_name = p.m_name;std::cout << "Person  copy constructor name: " << this->m_name << std::endl;
}// -----------------------
// main.cpp
#include<iostream> 
#include "person.h"void testFunc1(Person p1, Person p2, Person p3)
{Person pp1("pp1");Person pp2("pp2");
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);Person p1("p1 ----");Person p2("p2 ----");Person p3("p3 ----");std::cout << " --------------" <<std::endl;testFunc1(p1,p2,p3);return a.exec();
}

 从输出结果可以看出,先执行的最右边的参数 p3 的拷贝构造函数,再依次执行 p2 、p1 参数 

参考链接:c/c++参数入栈顺序和参数计算顺序 - 知乎 (zhihu.com)

               C++ 函数压栈与出栈 - 知乎

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Bert101】变压器模型背后的复杂数学【01/4】

一、说明 众所周知&#xff0c;变压器架构是自然语言处理&#xff08;NLP&#xff09;领域的突破。它克服了 seq-to-seq 模型&#xff08;如 RNN 等&#xff09;无法捕获文本中的长期依赖性的局限性。变压器架构被证明是革命性架构&#xff08;如 BERT、GPT 和 T5 及其变体&…

RocketMQ 延迟消息

RocketMQ 延迟消息 RocketMQ 消费者启动流程 什么是延迟消息 RocketMQ 延迟消息是指&#xff0c;生产者发送消息给消费者消息&#xff0c;消费者需要等待一段时间后才能消费到。 使用场景 用户下单之后&#xff0c;15分钟未支付&#xff0c;对支付账单进行提醒或者关单处理…

走进知识图谱(二)【世界知识图谱篇】知识表示的经典模型与平移模型及基于复杂关系建模的知识表示学习

上篇文章提到&#xff0c;该系列文章将主要围绕世界知识图谱和语言知识图谱这两大类知识图谱进行展开&#xff0c;并且提到知识图谱的主要研究包括了知识表示学习、知识自动获取和知识的推理与应用三大部分。今天主要介绍世界知识图谱的知识表示学习&#xff0c;其中包括经典的…

使用C语言实现UDP消息接收

目录 简介:步骤:步骤 1: 创建套接字步骤 2: 接收消息步骤 3: 完成 函数及变量解释总结: 简介: 在网络通信中&#xff0c;UDP&#xff08;User Datagram Protocol&#xff09;是一种无连接协议&#xff0c;它提供了一种快速、高效的数据传输方法。本文将向您展示如何使用C语言编…

Spring Bean 生命周期的执行流程

问题描述 Spring 生命周期全过程大致分为五个阶段&#xff1a; 1、创建前准备阶段 2、创建实例阶段 3、依赖注入阶段 4、 容器缓存阶段 5、销毁实例阶段 下图是 Spring Bean 生命周期完整流程图&#xff0c;其中对每个阶段的具体操作做了详细介绍&#xff1a; 一、创建前准备阶…

栈和队列详解

目录 栈 栈的概念及结构&#xff1a; 栈的实现&#xff1a; 代码实现&#xff1a; Stack.h stack.c 队列&#xff1a; 概念及结构&#xff1a; 队列的实现&#xff1a; 代码实现&#xff1a; Queue.h Queue.c 拓展&#xff1a; 循环队列&#xff08;LeetCode题目链接&#xff0…

每天一道leetcode:516. 最长回文子序列(动态规划中等)

今日份题目&#xff1a; 给你一个字符串 s &#xff0c;找出其中最长的回文子序列&#xff0c;并返回该序列的长度。 子序列定义为&#xff1a;不改变剩余字符顺序的情况下&#xff0c;删除某些字符或者不删除任何字符形成的一个序列。 示例1 输入&#xff1a;s "bbb…

【高频面试题】JVM篇

文章目录 一、JVM组成1.什么是程序计数器2.什么是Java堆&#xff1f;3.能不能介绍一下方法区(元空间&#xff09;4.你听过直接内存吗5.什么是虚拟机栈6.垃圾回收是否涉及栈内存&#xff1f;7.栈内存分配越大越好吗&#xff1f;8.方法内的局部变量是否线程安全&#xff1f;9.什么…

【技巧】如何保护PowerPoint不被改动?

PPT&#xff0c;也就是PowerPoint&#xff0c;是很多小伙伴在工作生活中经常用到的图形演示文稿软件。 做好PPT后&#xff0c;担心自己不小心改动了或者不想他人随意更改&#xff0c;我们可以如何保护PPT呢&#xff1f;下面小编就来分享两个常用的方法&#xff1a; 1. 将PPT改…

吉利科技携手企企通,打造集团化数智供应链系统

近日&#xff0c;吉利科技集团有限公司&#xff08;以下简称“吉利科技”&#xff09;联合企企通成功召开SRM采购供应链管理项目启动会。企企通与吉利科技高层、项目负责人与团队成员出席此次启动会。 双方将携手在企业供应商全生命周期管理、采购全流程、电子招投标、采购分析…

阿里云预装LAMP应用导致MySQL不显示访问密码如何解决

&#x1f600;前言 本篇博文是关于阿里云云服务器ECS部署MySQL过程中出现的一下坑&#xff0c;希望能够帮助到您&#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家…

【问题解决】Git命令行常见error及其解决方法

以下是我一段时间没有使用xshell&#xff0c;然后用git命令行遇到的一些系列错误和他们的解决方法 遇到了这个报错&#xff1a; fatal: Not a git repository (or any of the parent directories): .git 我查阅一些博客和资料&#xff0c;可以解决的方式&#xff1a; git in…