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

news2024/12/24 8:08:56
  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();
        // 在这里无法访问localVariable
        return 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.coloradmin.cn/o/2264617.html

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

相关文章

【java基础系列】实现一个简单的猜数字小游戏

主要是用的java中的键盘录入和随机数两个api&#xff0c;实现这种人机交互的小游戏&#xff0c;可以用来锻炼基础算法思维 实现效果 实现代码 package com.gaofeng.day10;import java.util.Random; import java.util.Scanner;/*** author gaofeng* date 2024-12-22 - 9:21*/ …

helm的介绍和安装

1 helm概述 1.1 资源对象难以管理的问题 helm是k8s资源清单的管理工具&#xff0c;它就像Linux下的包管理器&#xff0c;比如centos的yum&#xff0c;ubuntu的apt helm&#xff1a;命令行工具&#xff0c;主要用于k8s的chart的创建&#xff0c;打包&#xff0c;发布和管理。…

AI,cursor快速上手思维导图

https://cursor101.com/zh/tutorial/learn-cursor-tab

ESP32S3 使用LVGL驱动LCD屏(ST7789主控)

ESP32S3 使用LVGL驱动LCD屏&#xff08;ST7789主控&#xff09; 目录 1 分析原理图 2 驱动、点亮LCD(ST7789) 2.1 在工程中添加目录、文件 2.2 添加esp_lvgl_port组件 2.3 对工程进行必要的配置 2.4 编写必要代码 3 烧录、验证 1 分析原理图 要使用SOC驱动LCD屏&#…

【hackmyvm】Zday靶机wp

HMVrbash绕过no_root_squash静态编译fogproject 1. 基本信息^toc 这里写目录标题 1. 基本信息^toc2. 信息收集2.1. 端口扫描2.2. 目录扫描 3. fog project Rce3.1. ssh绕过限制 4. NFS no_root_squash5. bash运行不了怎么办 靶机链接 https://hackmyvm.eu/machines/machine.ph…

neo4j console 报错

项目场景&#xff1a; neo4j 开启失败 问题描述 在终端打开 neo4j 失败打开cmd, 输入: neo4j console 报错 原因分析&#xff1a; 1 可能是没有配置环境变量2 当前脚本的执行策略有问题 解决方案&#xff1a; 解决没有配置环境变量 添加环境变量 在path路径中将变量添加进去…

范德蒙矩阵(Vandermonde 矩阵)简介:意义、用途及编程应用

参考&#xff1a; Introduction to Applied Linear Algebra – Vectors, Matrices, and Least Squares Stephen Boyd and Lieven Vandenberghe 书的网站: https://web.stanford.edu/~boyd/vmls/ Vandermonde 矩阵简介&#xff1a;意义、用途及编程应用 在数学和计算科学中&a…

编译原理复习---正则表达式+有穷自动机

适用于电子科技大学编译原理期末考试复习。 1. 正则表达式 正则表达式&#xff08;Regular Expression&#xff0c;简称regex或regexp&#xff09;是一种用于描述、匹配和操作文本模式的强大工具。它由一系列字符和特殊符号组成&#xff0c;这些字符和符号定义了一种搜索模式…

CAD跨图纸复制与粘贴怎么操作?教程来了

在过去&#xff0c;图纸的复制粘贴工作大多依赖于电脑完成&#xff0c;手机则因运行内存等硬件限制&#xff0c;难以像电脑那样轻松实现多图同开&#xff0c;以及图纸内容的跨图复制粘贴。为解决这一痛点&#xff0c;CAD看图王手机端推出了跨图复制与粘贴功能&#xff0c;为用户…

算法训练第二十三天|93. 复原 IP 地址 78. 子集 90. 子集 II

93. 复原 IP 地址--分割 题目 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1a;"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址&…

Go怎么做性能优化工具篇之基准测试

一、什么是基准测试&#xff08;Benchmark&#xff09; 在 Go 中&#xff0c;基准测试是通过创建以 Benchmark 开头的函数&#xff0c;并接收一个 *testing.B 类型的参数来实现的。testing.B 提供了控制基准测试执行的接口&#xff0c;比如设置测试执行的次数、记录每次执行的…

【贪吃蛇小游戏 - JavaIDEA】基于Java实现的贪吃蛇小游戏导入IDEA教程

有问题请留言或私信 步骤 下载项目源码&#xff1a;项目源码 解压项目源码到本地 打开IDEA 左上角&#xff1a;文件 → 新建 → 来自现有源代码的项目 找到解压在本地的项目源代码文件&#xff0c;点击确定 选择“从现有项目创建项目”。点击“下一步” 点击下一步&a…

LabVIEW手机屏幕耐冲击测试

开发了一个基于LabVIEW的智能手机屏幕耐冲击测试系统。系统利用LabVIEW软件与高精度传感器&#xff0c;对手机屏幕进行落球冲击试验&#xff0c;以测定其耐冲击性能。这项技术不仅提高了测试的精度和效率&#xff0c;而且对智能手机屏幕的质量控制和改进提供了科学依据。 项目背…

Python + 深度学习从 0 到 1(01 / 99)

希望对你有帮助呀&#xff01;&#xff01;&#x1f49c;&#x1f49c; 如有更好理解的思路&#xff0c;欢迎大家留言补充 ~ 一起加油叭 &#x1f4a6; 欢迎关注、订阅专栏 【深度学习从 0 到 1】谢谢你的支持&#xff01; ⭐ 深度学习之前&#xff1a;机器学习简史 什么要了解…

FPGA学习(基于小梅哥Xilinx FPGA)学习笔记

相关资源网站&#xff08;小梅哥FPGA&#xff09; https://www.corecourse.cn/forum.php?modviewthread&tid27978 https://www.corecourse.cn/forum.php?modviewthread&tid28730 本篇文章使用的开发板为&#xff1a; 小梅哥 Xilinx FPGA 型号&#xff1a;XC7A35T 芯…

网安瞭望台第17期:Rockstar 2FA 故障催生 FlowerStorm 钓鱼即服务扩张现象剖析

国内外要闻 Rockstar 2FA 故障催生 FlowerStorm 钓鱼即服务扩张现象剖析 在网络安全的复杂战场中&#xff0c;近期出现了一个值得关注的动态&#xff1a;名为 Rockstar 2FA 的钓鱼即服务&#xff08;PhaaS&#xff09;工具包遭遇变故&#xff0c;意外推动了另一个新生服务 Flo…

aws(学习笔记第十九课) 使用ECS和Fargate进行容器开发

aws(学习笔记第十九课) 使用ECS和Fargate进行容器开发 学习内容&#xff1a; 使用本地EC2中部署docker应用使用ECS的EC2模式进行容器开发使用ECS的Fargate模式进行容器开发 1. 使用本地EC2中部署docker应用 docker整体 这里展示了docker的整体流程。 开发阶段 编写dockerfile…

【Python 图片下载器】一款专门为爬虫制作的图片下载器,多线程下载,速度快,支持续传/图片缩放/图片压缩/图片转换

文章日期&#xff1a;2024.12.23 使用工具&#xff1a;Python 本章知识&#xff1a;制作一款图片下载器_DOS窗口&#xff08;爬虫专用&#xff09; 文章难度&#xff1a;低等&#xff08;没难度&#xff09; 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要…

关于博客系统的自动化功能测试报告

1.项目背景 基于 SSM 的个人博客系统测试 博客系统采用前后端分离的方法来实现&#xff0c;同时使用了数据库来存储相关的数据&#xff0c;前端主要有四个页面构成:登录页、列表页、详情页以及编辑页&#xff0c;模拟实现了个人博客列表页面&#xff0c;其结合后端实现了以下的…

计算机的错误计算(一百八十九)

摘要 用大模型计算 tan(12.345) . 自变量取弧度。结果保留10位有效数字。不同于前面两节的大模型&#xff0c;本节调用了新的两个大模型。然而&#xff0c;很遗憾&#xff0c;它们给出的答案似乎仍然是“匹配”出来的&#xff0c;不是计算出来的。当然&#xff0c;均是错误的。…