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

c++------------------函数

  1. 函数定义

    • 语法格式
      • 函数定义包括函数头和函数体。函数头包含返回类型、函数名和参数列表。函数体是用花括号{}括起来的代码块,用于实现函数的功能。例如,定义一个计算两个整数之和的函数:
      int add(int a, int b) {return a + b;
      }
      
      这里int是返回类型,表示函数返回一个整数;add是函数名;(int a, int b)是参数列表,说明函数接受两个整数参数ab{ return a + b; }是函数体,实现了将两个参数相加并返回结果的功能。
    • 函数体中的变量作用域
      • 在函数体内部定义的变量具有局部作用域,它们只在函数内部有效。例如:
      void function() {int localVariable = 10;std::cout << localVariable << std::endl;
      }
      int main() {function();// 在这里无法访问localVariablereturn 0;
      }
      
      这里localVariablefunction函数内部定义,所以只能在function函数内部使用,在main函数或者其他函数中无法访问。
  2. 函数原型(声明)

    • 作用和必要性
      • 函数原型主要用于告诉编译器函数的名称、返回类型和参数类型等信息,使得编译器在编译调用该函数的代码时能够进行正确的类型检查。这样可以将函数的定义放在调用它的代码之后,或者放在其他文件中。例如,如果有一个函数定义在另一个文件中,在调用这个函数的文件中就需要提供函数原型。
    • 语法格式
      • 函数原型的语法格式为:返回类型 函数名(参数类型列表);。例如,int add(int a, int b);是前面定义的add函数的原型。注意,函数原型的末尾需要有一个分号。
    • 函数原型与函数定义的区别
      • 函数原型只是函数的声明,不包含函数体,它主要用于编译器的类型检查。而函数定义包含了函数体,是函数功能的具体实现。例如,在一个大型项目中,可以先在头文件中提供函数原型,然后在源文件中实现函数定义。
  3. 函数重载

    • 概念和目的
      • 函数重载是指在同一个作用域内,可以定义多个同名函数,只要它们的参数列表不同(参数个数、参数类型或者参数顺序不同)。函数重载的目的是为了方便程序员使用相似功能的函数,根据不同的参数情况执行不同的操作。例如,定义两个add函数,一个用于计算两个整数相加,另一个用于计算两个浮点数相加:
      int add(int a, int b) {return a + b;
      }
      double add(double a, double b) {return a + b;
      }
      
    • 编译器如何区分重载函数
      • 编译器通过检查函数调用时的实际参数类型和个数来确定调用哪一个重载函数。例如,在int result1 = add(3, 5);中,编译器会根据参数35是整数,调用int add(int a, int b)函数;而在double result2 = add(3.0, 5.0);中,编译器会调用double add(double a, double b)函数。
    • 重载函数的匹配规则和注意事项
      • 当调用一个重载函数时,编译器首先会寻找完全匹配的函数,如果没有完全匹配的,会尝试进行一些隐式类型转换来找到合适的函数。但是,如果存在二义性(即有多个函数都可以匹配,但编译器无法确定唯一的一个),则会导致编译错误。例如,有一个函数void func(int a);和另一个函数void func(double a);,在调用func(3.5f)3.5f是单精度浮点数)时,编译器可能会因为不知道是将3.5f转换为整数还是双精度浮点数而产生二义性错误。
  4. 默认参数

    • 概念和语法格式
      • 默认参数是指在函数定义或声明时,可以为参数指定一个默认值。在调用函数时,如果没有提供该参数的值,就会使用默认值。语法格式为:返回类型 函数名(参数类型 参数名 = 默认值);。例如:
      int multiply(int a, int b = 2) {return a * b;
      }
      
      这里b是有默认值的参数,默认值为2
    • 默认参数的使用规则和注意事项
      • 默认参数必须从右向左连续定义,不能间隔。例如,int func(int a = 1, int b, int c = 3);这样的定义是错误的。在调用有默认参数的函数时,可以省略默认参数的值,例如,int result1 = multiply(3);这里会使用b的默认值2,计算结果为6;也可以提供新的值,例如,int result2 = multiply(3, 4);这里b的值为4,计算结果为12。同时,在函数的声明和定义中,如果同时出现默认参数,建议在声明中指定默认参数,定义中可以不用再次指定(如果指定,必须与声明中的默认参数一致),以避免重复定义带来的不一致问题。

在这里插入图片描述

  1. 栈帧的创建与销毁

    • 栈帧创建过程
      • 当一个函数被调用时,系统会在程序的栈空间中为该函数创建一个栈帧。首先,会将函数的返回地址(即调用该函数的下一条指令的地址)压入栈中,这确保函数执行完后能回到正确的位置继续执行后续代码。然后,根据函数参数的类型和数量,将参数的值(如果是值传递)或引用(如果是引用传递)或指针(如果是指针传递)依次压入栈中。最后,为函数内部定义的局部变量分配内存空间。
      • 例如,有函数void func(int a, int b),当调用func(3, 4)时,系统会先将返回地址压入栈,然后将34压入栈作为参数ab的值,接着为func函数内部可能定义的局部变量预留空间。
    • 栈帧销毁过程
      • 当函数执行结束(遇到return语句或者函数体的最后一个花括号)时,栈帧会被销毁。首先,会释放函数内部局部变量所占用的内存空间。然后,根据函数的返回值类型(如果有返回值),将返回值复制到一个临时存储位置(如果是基本数据类型)或者通过移动语义(如果是对象)将返回值传递给调用者。最后,将栈顶指针恢复到调用该函数之前的位置,这样就相当于销毁了这个栈帧,同时将返回地址从栈中弹出,程序继续从返回地址处执行。
  2. 参数传递方式的细节

    • 值传递深入理解
      • 复制过程:在值传递中,实际参数的值会被完整地复制到函数的形式参数中。对于基本数据类型,这是一个简单的字节复制过程。例如,传递一个int类型的参数,会将该int值的字节序列复制到函数参数对应的内存位置。对于自定义结构体等复杂类型,会递归地复制每个成员变量的值。
      • 对原始参数的影响:由于是复制了一份新的值给函数参数,所以在函数内部对参数的修改不会影响到原始的实际参数。例如,对于函数void modify(int num),在函数内部num = 10,但如果在函数外部有int original_num = 5; modify(original_num);original_num的值依然是5
    • 引用传递深入理解
      • 引用的本质:引用在底层实现上可以看作是一个指针常量,它总是指向被引用的对象。当进行引用传递时,实际上传递的是对象的地址,但是在语法上使用起来就像使用原始对象一样。例如,int& ref = original_num;reforiginal_num在内存中指向同一个位置。
      • 对原始参数的影响:因为引用和原始对象共享同一块内存空间,所以在函数内部通过引用对参数进行操作,实际上就是对原始对象进行操作。例如,函数void modifyByReference(int& num),在函数内部num = 10,如果在函数外部有int original_num = 5; modifyByReference(original_num);original_num的值会变为10
    • 指针传递深入理解
      • 指针的操作方式:指针传递是把变量的地址传递给函数。在函数内部,通过解引用指针(使用*操作符)来访问和修改指针所指向的变量的值。例如,函数void modifyByPointer(int* ptr),当传递&original_num作为参数时,在函数内部通过*ptr = 10来修改original_num的值。
      • 与引用传递的区别:虽然指针传递和引用传递都可以在函数内部修改原始变量的值,但指针传递需要显式地解引用指针来访问变量,而引用传递在语法上更简洁,直接使用引用变量就可以访问和修改原始变量。另外,指针可以在函数内部重新赋值指向其他对象,而引用一旦初始化就不能再引用其他对象。
  3. 函数返回值传递机制的细节

    • 基本数据类型返回值传递
      • 复制返回值:当函数返回一个基本数据类型(如intdouble等)的值时,函数会将返回值复制到一个临时存储位置。这个临时存储位置可能是一个寄存器或者栈中的某个位置,具体取决于编译器和硬件架构。例如,对于函数int add(int a, int b) { return a + b; },当调用add函数时,计算a + b的结果会被复制到这个临时位置,然后这个值再被赋值给接收返回值的变量(如int result = add(3, 5);中的result)。
    • 对象返回值传递
      • 返回值优化(RVO):当函数返回一个对象时,C++编译器可能会应用返回值优化。在没有返回值优化的情况下,函数会先创建一个临时对象,将函数内部的对象复制到这个临时对象中(通过调用复制构造函数),然后返回这个临时对象。但是,通过返回值优化,编译器可以直接将函数内部的对象构造到接收返回值的对象的内存空间中,避免了不必要的复制操作。例如,对于函数MyClass createObject(),如果MyClass是一个自定义类,在合适的条件下,编译器会直接将createObject函数内部构造的MyClass对象构造到接收返回值的MyClass对象中,而不是先复制到一个临时对象再进行赋值。
      • 移动语义(Move Semantics):如果编译器没有进行返回值优化,除了复制构造函数外,C++还提供了移动构造函数来更高效地处理对象返回值。移动构造函数允许将一个对象的资源(如动态分配的内存)“移动”到另一个对象中,而不是进行复制。例如,对于一个包含动态分配数组的类,移动构造函数可以将数组的指针从一个对象转移到另一个对象,避免了重新分配内存和复制数组元素的开销。当函数返回对象时,编译器可能会优先调用移动构造函数(如果定义了)来提高效率。

在这里插入图片描述

相关文章:

c++------------------函数

函数定义 语法格式 函数定义包括函数头和函数体。函数头包含返回类型、函数名和参数列表。函数体是用花括号{}括起来的代码块&#xff0c;用于实现函数的功能。例如&#xff0c;定义一个计算两个整数之和的函数&#xff1a; int add(int a, int b) {return a b; }这里int是返回…...

软件信息化平台项目投标技术方案中如何进行项目实施方案以及安全质量方案培训售后方案应急预案的编写?

在软件平台投标技术方案中,项目实施方案、质量管理、安全管理、培训方案、售后服务方案和应急预案等章节至关重要,它们分别从不同角度确保项目的顺利实施、高质量交付、安全稳定运行、用户有效使用、持续服务保障以及应对突发情况的能力。各章节编制要点相互关联、协同作用,…...

Apache Tomcat 漏洞CVE-2024-50379条件竞争文件上传漏洞 servlet readonly spring boot 修复方式

1&#xff0c;关于漏洞 Apache Tomcat是一个流行的开源 Web 服务器和 Java Servlet 容器。 二、 漏洞描述 Apache Tomcat中修复了个 TOCTOU 竞争条件远程代码执行漏洞 (CVE-2024-50379)&#xff0c;该漏洞的 CVSS 评分为 9.8。Apache Tomcat 中 JSP 编译期间存在检查时间使用时…...

中国信通院致信感谢易保全:肯定贡献能力,期许未来合作

近日&#xff0c;中国信息通信研究院&#xff08;以下简称“中国信通院”&#xff09;向易保全发感谢信表达谢意&#xff0c;对其在中国信通院牵头的“铸基计划”——企业数字化转型高质量发展推进行动实施中展现出的重要贡献给予了高度评价和肯定&#xff0c;并展望了双方至20…...

20241220流水的日报 mysql的between可以用于字符串 sql 所有老日期的,保留最新日期

1.F310A RKP有效性验证讨论&#xff1a;需连外网&#xff0c;需先用app生成标志&#xff0c;工具读标志。 2.M200 适配一个 给客户写配置的工具 mysql的between可以用于字符串 批量打印包装箱时&#xff0c;提示有重复N条的处理方法&#xff1a; --先备份数据库&#xff0c;删…...

低代码开源项目Joget的研究——安装部署

大纲 环境准备安装必要软件配置Java配置JAVA_HOME配置Java软链安装三方库 获取源码配置MySql数据库创建用户创建数据库导入初始数据 配置数据库连接配置sessionFactory编译下载tomcat启动下载aspectjweaver移动jw.war文件编写脚本运行 测试参考资料 Joget&#xff0c;作为一款开…...

《鸿蒙开发-答案之书》字符串占位符格式化

《鸿蒙开发-答案之书》字符串占位符格式化 先在string.json定义&#xff1a; {"name":"message_arrive","value":"We will arrive at %s."}使用&#xff0c;它有两种使用方式&#xff1a; 方式一&#xff1a; Text($r(app.string.…...

workman服务端开发模式-应用开发-gateway长链接端工作原理

一、长链接的工作原理 Register类其实也是基于基础的Worker开发的。Gateway进程和BusinessWorker进程启动后分别向Register进程注册自己的通讯地址&#xff0c;Gateway进程和BusinessWorker通过Register进程得到通讯地址后&#xff0c;就可以建立起连接并通讯了。而Gateway进程…...

Android 关于Tencent vConsole 添加入webView 总结

官方地址&#xff1a; https://github.com/Tencent/vConsole/blob/dev/doc/tutorial_CN.md 上面文档中提供了两种常见的引入H5工程思路&#xff0c;简单易懂&#xff01; 今天这篇文章要说明的是&#xff0c;不同于官方文档的接入方式。 先说背景&#xff1a;H5工程方&…...

【路径规划】原理及实现

路径规划&#xff08;Path Planning&#xff09;是指在给定地图、起始点和目标点的情况下&#xff0c;确定应该采取的最佳路径。常见的路径规划算法包括A* 算法、Dijkstra 算法、RRT&#xff08;Rapidly-exploring Random Tree&#xff09;等。 目录 一.A* 1.算法原理 2.实…...

【AIGC】ChatGPT 结构化 Prompt 的高级应用

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;标识符的使用&#xff08;Use of Identifiers&#xff09;1. #2. <>3. - 或 4. [] &#x1f4af;属性词的重要性和应用应用场景 &#x1f4af;具体模块…...

Go web 开发框架 Iris

背景 掌握了 Go 语言的基础后就该开始实践了&#xff0c;编写Web应用首先需要一个 web 开发框架。做框架选型时&#xff0c;处理web请求是基本功能&#xff0c;至于MVC是更进一步需要。现在比较流行的web架构是前后端分离&#xff0c;后端响应RESTful的请求&#xff0c;Iris 能…...

uniapp Native.js 调用安卓arr原生service

最近搞了个uni小项目&#xff0c;一个定制的小平板&#xff0c;带一个nfc设备&#xff0c;厂家只给了一套安卓原生demo&#xff0c;头一次玩原生安卓&#xff0c;废了好半天劲打出来arr包&#xff0c;想镶进uniapp里&#xff0c;网上查了好久&#xff0c;都是错的&#xff0c;要…...

C#代码实现把中文录音文件(.mp3 .wav)转为文本文字内容

我们有一个中文录音文件.mp3格式或者是.wav格式&#xff0c;如果我们想要提取录音文件中的文字内容&#xff0c;我们可以采用以下方法&#xff0c;不需要使用Azure Speech API 密钥注册通过离线的方式实现。 1.首先我们先在NuGet中下载两个包 NAudio 2.2.1、Whisper.net 1.7.3…...

【一文了解】C#重点-委托1

本篇文章来学习一下C#的委托&#xff0c;委托是C#中的一个重要概念&#xff0c;它允许将方法作为参数传递给其他方法。C#中的委托类似于C或C中的函数指针&#xff0c;并且类型安全。 委托 1.委托的定义 委托&#xff08;delegate&#xff09;是方法的代理/代表&#xff0c;委托…...

WPF+MVVM案例实战与特效(四十五)- 打造优雅交互:ListBox 的高级定制与行为触发(侧边菜单交互面板)

文章目录 1、引言2、案例效果3、案例实现1、依赖安装2、文件创建3、代码实现1、依赖引用与上下文2、个性化视觉效果:自定义 ItemContainerStyle3、页面样式与布局完整代码4、ViewModel 逻辑实现5、子界面代码:3、实现效果4、源代码获取5、总结1、引言 在WPF应用程序开发中,…...

新版Android Studio 2024.1.2版本,如何通过无线wifi连接手机实现交互

1、首先&#xff0c;先确定手机是否启动了开发者选项 在我的设备 -> 全部参数 -> MIUI版本点击6下 &#xff08;有的手机是 关于手机 -> 查看手机版本 &#xff09; 2、在设置中搜索 开启开发者选项 3、进入开发者选项后&#xff0c;在 调试 中选择 无线调试并选择…...

VTK知识学习(26)- 图像基本操作(一)

1、前言 图像处理离不开一些基本的图像数据操作&#xff0c;例如获取和修改图像的基本信息、访问和修改图像像素值、图像显示、图像类型转换等。熟练掌握这些基本操作有助于使用 VTK进行图像处理应用程序的快速开发。 2、图像信息的访问与修改 1&#xff09;利用vtkIamgeData…...

2024年9月AI头条新闻:创新与挑战并存

2024年9月AI头条新闻&#xff1a;创新与挑战并存 9月&#xff0c;人工智能领域继续高速发展&#xff0c;重大产品发布、伦理争议和技术突破交织在一起。让我们回顾一下本月最重要的AI新闻&#xff1a; OpenAI的o1&#xff1a;更强大的语言模型 OpenAI推出了o1&#xff0c;一个…...

[Xshell] Xshell的下载安装使用、连接linux、 上传文件到linux系统-详解(附下载链接)

前言 xshell 链接&#xff1a;https://pan.quark.cn/s/57062561e81a 提取码&#xff1a;TK4K 链接失效&#xff08;可能被官方和谐&#xff09;可评论或私信我重发 安装 下载后解压得到文件 安装路径不要有中文 打开文件 注意&#xff01;360等软件会拦截创建注册表的行为&a…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)

题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...

多元隐函数 偏导公式

我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式&#xff0c;给定一个隐函数关系&#xff1a; F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 &#x1f9e0; 目标&#xff1a; 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z​、 …...

LangChain【6】之输出解析器:结构化LLM响应的关键工具

文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器&#xff1f;1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...

20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题

20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题 2025/6/9 20:54 缘起&#xff0c;为了跨网段推流&#xff0c;千辛万苦配置好了网络参数。 但是命令iptables -t filter -F tetherctrl_FORWARD可以在调试串口/DEBUG口正确执行。…...