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++还提供了移动构造函数来更高效地处理对象返回值。移动构造函数允许将一个对象的资源(如动态分配的内存)“移动”到另一个对象中,而不是进行复制。例如,对于一个包含动态分配数组的类,移动构造函数可以将数组的指针从一个对象转移到另一个对象,避免了重新分配内存和复制数组元素的开销。当函数返回对象时,编译器可能会优先调用移动构造函数(如果定义了)来提高效率。

在这里插入图片描述

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

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

相关文章

如何在centos系统上挂载U盘

在CentOS上挂载NTFS格式的U盘,需要执行一系列步骤,包括识别U盘设备、安装必要的软件、创建挂载点,并最终挂载U盘。以下是在CentOS上挂载NTFS格式U盘的详细步骤: 一、准备工作 确认CentOS版本: 确保你的CentOS系统已经安装并正常运行。不同版本的CentOS在命令和工具方面可能…

Excel中match()函数

函数功能概述 MATCH 函数是 Excel 中用于在指定区域中查找特定值的位置的函数。它返回指定数值在指定数组区域中的位置。这个位置是相对于查找区域的相对位置&#xff0c;而不是绝对的单元格位置。语法结构 MATCH(lookup_value, lookup_array, match_type)lookup_value&#xf…

解决树形列表中数值层级累加

一、场景 记录解决树形列表中&#xff0c;父级中的某个属性需要由自身和子集累加的一个方法(递归)。 二、解决方案 public static void main(String[] args) throws Exception {List<NewsCategoryStaticDto> dataList new ArrayList<>();/*** 构造树形列表数据*…

【工作流】工作顺序

背景 当时的情况是&#xff1a;没有产品经理&#xff0c;后端直接和需求方对接&#xff1b;前端只能短时间投入大部分时间要忙别的&#xff1b;只有3个角色&#xff1a;需求方&#xff0c;后端&#xff0c;前端&#xff1b; 当时直接执行的 直接使用会议了解需求&#xff0c…

【人工智能-数据集】RML2018 时域信号的时序信号和星座图的图片信号生成方式(可用于多模态特征融合)

RML2018 数据集处理与多模态数据集生成指南 在现代无线通信和机器学习的交叉领域,数据集的质量和多样性对于模型的性能至关重要。RML2018 数据集作为一个涵盖多种调制方式和信噪比(SNR)的丰富资源,广泛应用于信号识别、调制分类等任务。本篇博客将深入介绍如何处理 RML201…

Android 获取屏幕物理尺寸

注&#xff1a;编译 sdk 需要使用 30 因为引入了 WindowMetrics、uild.VERSION_CODES.R 新 sdk 才存在的类和属性 某些场景处理 view &#xff0c;对 view 显示的位置要求比较精确&#xff0c;通常我们使用context.getResources().getDisplayMetrics().widthPixels 获取到的宽、…

sqoop的参数有哪些?

Sqoop 是一款用于在 Hadoop 与关系型数据库之间进行数据传输的工具&#xff0c;它有很多参数&#xff0c;可分为通用参数、导入参数和导出参数等&#xff0c;以下是一些常见的参数介绍&#xff1a; 通用参数 --connect 说明&#xff1a;指定要连接的关系型数据库的 JDBC URL。…

不同路径

不同路径 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&#xff…

NS3学习——tcpNewReno算法代码详解(2)

NS3学习——tcpNewReno算法代码详解&#xff08;1&#xff09;-CSDN博客 目录 二、详解 4.TCP NewReno的注册和构造部分 5. TcpNewReno慢启动算法 6. TcpNewReno拥塞避免算法 7.IncreaseWindow函数的实现 8.其他成员函数的实现 8.1 GetName函数 8.2 GetSsThresh函数 …

OpenCV相机标定与3D重建(26)计算两个二维点集之间的部分仿射变换矩阵(2x3)函数 estimateAffinePartial2D()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算两个2D点集之间的具有4个自由度的最优有限仿射变换。 cv::estimateAffinePartial2D 是 OpenCV 库中的一个函数&#xff0c;用于计算两个二维…

计算机网络——练习题

一. 单选题&#xff08;共27题&#xff0c;67.5分&#xff09; 1. (单选题)计算机网络的最突出的优点是____。 A. 运算速度快 B. 运算精度高 C. 存储容量大 D. 资源共享 我的答案: D:资源共享;正确答案: D:资源共享; 2.5分 答案解析&#xff1a; 2. (单选题)TCP/IP协…

C++打造局域网聊天室第十课: 客户端编程及数据发送

文章目录 前言一、补充内容&#xff0c;设置显示框换行二、客户端编程三、封装消息发送函数四、所处的身份状态总结 前言 C打造局域网聊天室第十课&#xff1a; 客户端编程及数据发送 一、补充内容&#xff0c;设置显示框换行 编辑框的显示内容默认是不会换行的&#xff0c;这…

理解神经网络

神经网络是一种模拟人类大脑工作方式的计算模型&#xff0c;是深度学习和机器学习领域的基础。 基本原理 神经网络的基本原理是模拟人脑神经系统的功能&#xff0c;通过多个节点&#xff08;也叫神经元&#xff09;的连接和计算&#xff0c;实现非线性模型的组合和输出。每个…

记Fastjson2的一个报ConcurrentModificationException的bug

错误背景&#xff1a;fastjson2的parseObject方法&#xff0c;在spring webflux项目中被调用&#xff0c;有时会报java.util.ConcurrentModificationException错误。报错处的代码如下图&#xff1a; 改了半天与并发安全相关的代码&#xff0c;还是会报此错误。后来改变思路搜…

智慧仓储可视化视频监控智能监管系统解决方案

一、背景与需求 对于现在很多大型工厂或者物流基地来说&#xff0c;仓库无疑是存放物品的重点场所。仓储存放着大量货物&#xff0c;同时存在大量的辅助设备&#xff0c;需要进行全方位的监管&#xff0c;以避免发生安全事故&#xff0c;造成财产损失。原有的人工巡检方式已无法…

voxelize_cuda安装 笔记

目录 windows 安装 linux安装&#xff0c;测试成功 cuda_voxelize python 测试&#xff1a; windows 安装 voxelize_cuda安装教程 pythonwindows环境-CSDN博客 linux安装&#xff0c;测试成功 git clone https://github.com/YuliangXiu/neural_voxelization_layer.gitpyt…

2024_12_20_生活记录

年底了&#xff0c;提前祝各位朋友们新年快乐&#xff01;我将近两年没动笔写blog了&#xff0c;主要确实挺忙。。。今天想简单聊聊自己的近期想法&#xff0c;一方面是职业规划&#xff0c;一方面是生信&#xff0c;最后是个人感悟。 职业规划 熟悉我的朋友们会了解我之前一直…

http反向代理

通过反向代理实现访问biying,目前访问一些网站需要绕过cloudfare还没有解决,代码如下: from fastapi import FastAPI, Request from fastapi.responses import StreamingResponse import httpx import uvicorn import logging# 设置日志 logging.basicConfig(level=logging.…

AI大模型与传统模型的六大区别

大模型&#xff0c;也被称为大型语言模型&#xff0c;是指使用大规模数据集训练的深度学习模型。 这些模型通常具有数十亿个参数&#xff0c;能够学习复杂的语言模式、生成连贯的文本、翻译语言、回答问题等。 大模型可以应用于多种自然语言处理任务&#xff0c;如文本生成、…

信息安全管理与评估赛题第9套

全国职业院校技能大赛 高等职业教育组 信息安全管理与评估 赛题九 模块一 网络平台搭建与设备安全防护 1 赛项时间 共计180分钟。 2 赛项信息 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段 网络平台搭建与设备安全防护 任务1 网络平台搭建 XX:XX- XX:XX 50 任务2…