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.mzph.cn/news/41561.shtml

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

相关文章

2020年3月全国计算机等级考试真题(C语言二级)

2020年3月全国计算机等级考试真题&#xff08;C语言二级&#xff09; 第1题 有以下程序 void fun1 (char*p) { char*q; qp; while(*q!\0) { (*Q); q&#xff1b; } } main() { char a[]{"Program"},*p; p&a[3]; fun1(p); print…

【C语言学习】本地变量

本地变量 1.函数每次运行&#xff0c;就会产生一个独立的变量空间&#xff0c;在这个空间中的变量&#xff0c;是函数的这次运行所独有的&#xff0c;称之为本地变量。 2.定义在函数内部的变量就是本地变量。 3.参数也是本地变量 变量的生存期和作用域 1.生存期&#xff1a;变量…

新能源电动车充电桩控制主板安全特点

新能源电动车充电桩控制主板安全特点 你是否曾经担心过充电桩的安全问题?充电桩主板又是什么样的呢?今天我们就来聊聊这个话题。 充电桩主板采用双重安全防护系统&#xff0c;包括防水、防护、防尘等&#xff0c;确保充电桩安全、可靠。不仅如此&#xff0c;充电桩主板采用先…

简单的洗牌算法

目录 前言 问题 代码展现及分析 poker类 game类 Text类 前言 洗牌算法为ArrayList具体使用的典例&#xff0c;可以很好的让我们快速熟系ArrayList的用法。如果你对ArrayList还不太了解除&#xff0c;推荐先看本博主的ArrayList的详解。 ArrayList的详解_WHabcwu的博客-CSD…

mysql mysql 容器 忽略大小写配置

首先能够连接上mysql&#xff0c;然后输入下面这个命令查看mysql是否忽略大小写 show global variables like %lower_case%; lower_case_table_names 0&#xff1a;不忽略大小写 lower_case_table_names 1&#xff1a;忽略大小写 mysql安装分为两种&#xff08;根据自己的my…

sql server Varchar转换为Datetime

将Varchar转换为Datetime是一个常见的需求&#xff0c;在处理日期和时间数据时特别有用。在SQL Server中&#xff0c;可以使用CONVERT函数或CAST函数将Varchar转换为Datetime。 使用CONVERT函数 CONVERT函数可以将一个值从一个类型转换为另一个类型。以下是使用CONVERT函数将…

FPGA芯片IO口上下拉电阻的使用

FPGA芯片IO口上下拉电阻的使用 为什么要设置上下拉电阻一、如何设置下拉电阻二、如何设置上拉电阻为什么要设置上下拉电阻 这里以高云FPGA的GW1N-UV2QN48C6/I5来举例,这个芯片的上电默认初始化阶段,引脚是弱上来模式,且模式固定不能通过软件的配置来改变。如下图所示: 上…

centos 7.x 单用户模式

最近碰到 centos 7.9 一些参数设置错误无法启动系统的情况&#xff0c;研究后可以使用单用户模式进入系统进行恢复操作。 进入启动界面&#xff0c;按 e ro 替换为 rw init/sysroot/bin/sh 替换前 替换后 Ctrl-x 进行重启进入单用户模式 执行 chroot /sysroot 可以查看日…

【ARM64 常见汇编指令学习 19 -- ARM64 BEQ与B.EQ的区别】

文章目录 ARM BEQ和B.EQ 上篇文章&#xff1a;ARM64 常见汇编指令学习 18 – ARM64 TST 指令与 条件标志位 Z ARM BEQ和B.EQ 在ARMv8汇编中&#xff0c;BEQ和B.EQ实际上是同一条指令的两种不同表示方式&#xff0c;它们都表示条件分支指令&#xff0c;当某个条件满足时&#x…

java练习4.快速查找

题目: 数组 arr[6,1,3,7,9,8,5,4,2],用快速排序进行升序排序. import java.util.Random;public class recursionDemo {public static void main(String[] args) {/*快速排序:* 第一轮:以0索引为基准数,确定基准数在数组正确的位置,* 比基准数小的放到左边,比基准数大的放在右边…

Scada和lloT有什么区别?

人们经常混淆SCADA&#xff08;监督控制和数据采集&#xff09;和IIoT&#xff08;工业物联网&#xff09;。虽然SCADA系统已经存在多年&#xff0c;但IIoT是一种相对较新的技术&#xff0c;由于其能够收集和分析来自各种设备的大量数据而越来越受欢迎。SCADA和IIoT都用于提高工…

leetcode原题:检查子树

题目&#xff1a; 检查子树。你有两棵非常大的二叉树&#xff1a;T1&#xff0c;有几万个节点&#xff1b;T2&#xff0c;有几万个节点。设计一个算法&#xff0c;判断 T2 是否为 T1 的子树。 如果 T1 有这么一个节点 n&#xff0c;其子树与 T2 一模一样&#xff0c;则 T2 为…

【学习笔记之vue】These dependencies were not found:

These dependencies were not found:方案一 全部安装一遍 我们先浅试一个axios >> npm install axios 安装完报错就没有axios了&#xff0c;验证咱们的想法没有问题&#xff0c;实行&#xff01; ok

Redis可以用作消息队列吗?如何实现简单的消息队列功能?

是的&#xff0c;Redis可以被用作简单的消息队列。下面是一种实现简单消息队列功能的方式&#xff1a; 生产者&#xff08;Producer&#xff09;端&#xff1a; 使用LPUSH命令将消息推送到一个列表中&#xff0c;作为消息队列的实现。例如&#xff0c;使用LPUSH命令将消息推送到…

算法练习Day50|● 123.买卖股票的最佳时机III ● 188.买卖股票的最佳时机IV

LeetCode:123.买卖股票的最佳时机III 123. 买卖股票的最佳时机 III - 力扣&#xff08;LeetCode&#xff09; 1.思路 将两次买入卖出转化为是否持有的状态&#xff0c;当天可进行两次买卖&#xff0c;故每天买卖有四种状态&#xff0c;四种状态包含了当天不买不卖的状态。 …

性能分析之MySQL慢查询日志分析(慢查询日志)

一、背景 MySQL的慢查询日志是MySQL提供的一种日志记录,他用来记录在MySQL中响应的时间超过阈值的语句,具体指运行时间超过long_query_time(默认是10秒)值的SQL,会被记录到慢查询日志中。 慢查询日志一般用于性能分析时开启,收集慢SQL然后通过explain进行全面分析,一…

使用PDF文件入侵任何操作系统

提示&#xff1a;我们8月28号开学,所以我得快点更新了&#xff0c;不能拖了&#x1f625; 文章目录 前言一、打开终端总结 前言 PDF文件被广泛应用于共享信息&#xff0c;电子邮件&#xff0c;网站或文档或存储系统的真实链接 它可以用于恶意软件的载体。 不要问我什么意思&am…

在项目中如何解除idea和Git的绑定

在项目中如何解除idea和Git的绑定 1、点击File--->Settings...(CtrlAltS)--->Version Control--->Directory Mappings--->点击取消Git的注册根路径&#xff1a; 2、回到idea界面就没有Git了&#xff1a; 3、给这个项目初始化 这样就可以重新绑定远程仓库了&#x…

Mysql查询

第三章&#xff1a;select 语句 SELECT employees.employee_id,employees.department_id FROM employees WHERE employees.employee_id176; DESC departments;SELECT * FROM departments;第四章&#xff1a;运算符使用 SELECT employees.last_name,employees.salary FROM em…

springboot使用mybatis配置多数据源,同时能使用mybatisplus

概述 配置多数据源有两种方案。一种是使用dynamic依赖的DS注解的方法&#xff0c;这种是比较简单方便的方法。另一种是本文介绍的方式&#xff0c;配置不同数据源的SqlSessionFactory 。 第二种方法是我在开发一个老项目时&#xff0c;老项目配置的方法。 application.xml s…