C++基础学习(DAY_06)

  • 函数
    • 1. 函数的定义与使用
    • 2. 函数参数传递
    • 3. 变量的声明周期
    • 4. 函数的其他特性
    • 5. 函数的嵌套与递归

函数

1. 函数的定义与使用

​ 在设计程序时,如果一段代码重复进行某种操作或者完成一个特定的功能,就应该将这些代码封装组织成函数,以实现代码复用。

  • 定义:函数类型 函数名(形式参数列表)
    {
    函数体中的语句组;
    }
    以上,函数由函数类型、函数名、函数参数组成,这部分称为函数头。函数名遵守标识符命名规则。
    大括号称为函数体,里面写函数执行的具体代码。
    函数定义时只能在全局范围定义,不能在局部定义,不能在函数内部再定义函数。
  • 函数类型与返回值:
    函数可以有返回值,也可以没有。
    函数类型就是指函数的返回值类型,可以是C++支持的任意类型。
    函数返回值是由return语句给出的。
    当函数不需要返回值的时候,返回值类型要用void空类型指定
  • 函数参数:
    形参(形式参数):定义函数时括号中的参数
    实参(实际参数):调用函数时括号中的参数
  • 函数调用:函数名(实参);

函数声明:
声明一个函数,就是写出函数的原型(函数头部),但没有写出函数体(实现部分)。主要用于告诉编译器,它的实现放在其他地方。
如果函数没有声明,调用的时候就要按照顺序书写,就要在前面定义好函数,后面才能调用函数。否则就会找不到函数报错。

2. 函数参数传递

函数实参可以是常量、变量、表达式。在函数调用时,系统为形参分配内存空间并且将实参的值传到形参的空间中。
根据函数的给你需要,可以选择三种不同的传参方式:值传递、指针传递、引用传递
1)值传递:实参的值传递给形参

2)指针传递:指针作为函数的参数

3)引用传递:引用传递本质上也是传递的地址
在这里插入图片描述

//值传递:用来交换主调函数中俩个变量的值。
void swap(int x,int y)
{cout << "&x=" << &x << " &y=" << &y << endl;int temp = x;x = y;y = temp;
}void test02()
{int n1 = 10, n2 = 20;cout << "&n1=" << &n1 << " &n2=" << &n2 << endl;swap(n1,n2);//交换n1,n2的值cout << "调用swap函数之后:" << endl;cout << n1 << " " << n2;//交换失败,原因:值传递只是把n1,n2实参的值传递给形参x和y,函数内部交换的是x、y,不会对n1、n2进行操作
}

在这里插入图片描述

//用指针传递,交换主调函数中俩个变量的值。
void swap_p(int* x,int* y)
{cout << "x=" << x << " y=" << y << endl;int temp = *x;*x = *y;*y = temp;
}void test03()
{int n1 = 10, n2 = 20;cout << "&n1=" << &n1 << " &n2=" << &n2 << endl;swap_p(&n1, &n2);//交换n1,n2的值cout << "调用swap_p函数之后:" << endl;cout << n1 << " " << n2;//交换成功,因为指针传递的是地址,函数内部操作的是n1和n2的地址。
}//用引用传递,交换主调函数中俩个变量的值。
void swap_r(int& x, int& y)
{cout << "&x=" << &x << " &y=" << &y << endl;int temp = x;x = y;y = temp;
}void test04()
{int n1 = 10, n2 = 20;cout << "&n1=" << &n1 << " &n2=" << &n2 << endl;swap_r(n1, n2);//交换n1,n2的值cout << "调用swap_r函数之后:" << endl;cout << n1 << " " << n2;//交换成功
}

引用传递与值传递用法上的区别:

  • 引用传递:调用函数时,实参只能是变量。主要用在复杂数据类型(自定义类型)传递时,可以节省空间和时间。
  • 值传递:调用函数时,实参可以使变量、常量或者表达式。
//俩个函数,分别是值传递和引用传递,计算圆的面积
double area1(double radius)
{double a = 3.14 * radius * radius;return a;
}
double area2(double& radius)
{double a = 3.14 * radius * radius;return a;
}void test05()
{double r = 10;//变量cout << "值传递:(变量)" << area1(r) << endl;cout<<"值传递:(常量)"<< area1(100) << endl;cout<<"值传递:(表达式)" << area1(r*2) << endl;cout << "引用传递:(变量)" << area2(r) << endl;//以下不支持//cout << "引用传递:(常量)" << area2(100) << endl;//cout << "引用传递:(表达式)" << area2(r * 2) << endl;
}

数组作为函数参数:
数组名实际上是数组的首元素地址,所以数组作为函数参数传递其实传递的是首元素地址,无法将整个数组传递。
同样如果想返回一个数组,也是返回一个指针。

//编写一个函数,将整型数组中的元素按照相反的顺序来存放,即翻转数组
void my_reverse(int* p,int n)//第一个元素传递的是数组的首地址,第二个参数传递的是数组的元素个数;仅凭数组的首地址,无法获取元素个数
{//用俩个指针实现交换,分别指向第一个元素和最后一个元素,然后一个指针往后走,一个指针往前走,直到他俩相遇。int* i, * j, temp;for (i = p, j = p + n - 1;i < j;i++, j--){temp = *i;*i = *j;*j = temp;}
}void test06()
{int a[10] = { 0,1,2,3,4,5,6,7,8,9 };int n = sizeof(a)/sizeof(int);my_reverse(a, n);for (size_t i = 0; i < n; i++){cout << a[i] << " ";}
}

3. 变量的声明周期

每个标识符都有确定的作用域,决定他们在什么范围内能被访问。
整个作用域又决定了他们的生命周期。

栈内存中的局部变量在进入它的作用域时在内存中创建,在离开它的作用域后,被编译器自动回收释放。
堆内存中的变量需要程序员自己管理,它的生命周期由程序员决定。

  • 局部变量和全局变量:
    函数内定义的变量是局部变量,他只在函数范围内有效。
    在函数外定义的变量是全局变量,它在整个文件内有效。
    全局变量在当前文件的任何函数中都可以访问。
    如果我们在不同的作用域下定义了多个同名变量的话,访问规则是优先访问作用域最小的那个(离你最近的那个)
    如果要在某个作用域下访问同名的全局变量,那么可以在变量前面加域运算符::

变量的存储方式:
1)静态存储
静态存储是指在程序运行期间,给变量分配的内存一直有效。
定义:static 数据类型 变量名;
2)动态存储
是指在程序运行期间,根据需要动态管理变量的内存空间。如局部变量,当执行到该函数时,就为局部变量分配空间,
当离开函数时,局部变量就被释放。下次在执行到该函数时,再重新分配。这些是通过编译器在栈内存自动完成的。
堆内存也属于动态存储,但是变量的生命周期由程序员自己决定。

4. 函数的其他特性

内联函数==(inline==):
就是将函数嵌入到可执行程序中,而不需要去调用的函数。
有一些函数需要频繁调用而且函数内部的代码规模很小,逻辑简单。为了减少函数调用的开销(包括寻找函数地址,传参…),
可以将这种函数设置为内联函数,相当于将他嵌入到函数的调用处。
注意:只有简单的函数才能成为内联函数,如果函数复杂,含有循环分支等结构,即使定义为内联函数,编译器也会当做普通函数处理。
定义:
inline 函数类型 函数名(形参列表);

  • 函数重载:
    可以定义多个同名,只要参数不同就可以(参数的个数或者类型不同即可)。
    调用时,编译器会根据实际参数来选择匹配的函数去调用。这称为重载。
  • 带默认参数值的函数:
    函数定义时,可以预先给某些参数指定默认值,如果函数调用时没有给出实际参数,就会采用默认值,如果给出实参就会替换默认值。
    注意:默认值必须从右往左依次给出。如果某个参数有默认值,那么它右边的所有参数都必须有默认值。
    错误示范:int max(int a,int b=10,int c);

5. 函数的嵌套与递归

函数的嵌套指的是函数调用函数,是函数的嵌套。函数定义是不能嵌套。

递归:递归就是函数调用自身,一个函数可以通过直接或者间接的方式来调用自己实现递归。
写递归函数的关键点:
1)明确函数的功能
明确函数接收什么参数,返回什么结果,完成什么逻辑。例如阶乘,功能就是接收1个整数n,计算并返回n的阶乘。
2)确定递归的终止条件
递归函数必须有终止条件,否则会陷入无线递归,最终会导致栈内存被沾满,叫做栈溢出。
终止条件是递归函数停止调用自身的条件,通常对应着最简单的情况。
3)找出递归关系
递归关系是如何将一个大问题分解为多个小问题的过程。在阶乘例子中,n的阶乘是个大问题,分解为小问题,就是n的阶乘=n*(n-1)的阶乘
4)要确保递归调用的参数能逐渐逼近终止条件
每次递归调用时,传递给递归函数的参数要向终止条件逼近,阶乘例子中,每次调用时,n都-1,保证了最终达到终止条件
5)处理递归的返回值
在递归函数中,要将每次调用的返回值用于当前问题的求解。


//用递归的方式求n的阶层
long power(int n)
{if(n==1 || n==0){return 1;}return n * power(n - 1);
}void test13()
{cout << "请输入一个整数,小于10" << endl;int n;cin >> n;cout << "它的阶乘=" << power(n) << endl;
}

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

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

相关文章

react+vite+ts 组件模板

1.创建项目npm create vitelatest my-app --template react-ts2.配置项目 tsconfig.json{"compilerOptions": {"target": "ES2020","useDefineForClassFields": true,"lib": ["ES2020", "DOM", "D…

C语言 - 输出参数详解:从简单示例到 alloc_chrdev_region

C语言中的输出参数详解&#xff1a;以 alloc_chrdev_region 为例 在学习 C 语言函数调用时&#xff0c;我们常常接触到“输入参数”&#xff0c;比如把一个数字传给函数&#xff0c;让函数帮我们算出结果。但有时候可能会发现&#xff0c;有些函数除了返回值之外&#xff0c;还…

机器视觉学习-day09-图像矫正

1 仿射变换与透视变换1.1 仿射变换之前在图像旋转实验中已经接触过仿射变换&#xff0c;仿射变换是一个二维坐标系到另一个二维坐标系的过程&#xff0c;在仿射变换中符合直线的平直性和平行性。1.2 透视变换透视变换是把一个图像投影到一个新的视平面的过程。在现实世界中&…

杰理ac791获取之前版本sdk

很惭愧&#xff0c;一个如此简单的问题卡了这么久&#xff0c;运动战的本质就是多找线索&#xff0c;多尝试

基于轴重转移补偿和多轴协调的粘着控制方法研究

基于轴重转移补偿和多轴协调的粘着控制方法研究 1. 论文标题 基于轴重转移补偿和多轴协调的粘着控制方法研究 2. 内容概括 该论文针对重载电力机车在复杂轨面条件下易发生空转的问题,提出了一种新型粘着控制方法。传统方法仅考虑单轴粘着利用而忽略轴间关系,本文设计了包…

台达 PLC 软件导入 EDS 文件后不能通过 PDO 控制的解决方法

一、功能及注意事项 1.功能说明&#xff1a;通过修改 EDS 文件处理台达 PLC 软件导入 EDS 文件后不能通过 PDO 控制的解决方法 2.注意事项&#xff1a;1).此文档只针对立迈胜 CANopen 通讯一体化电机&#xff1b; 2).EDS 文件可以用记事本打开&#xff1b; 二、EDS 文件修改 IS…

Python库2——Matplotlib2

上一篇文章主要介绍了Matplotlib库中的Pyplot模块中几大常见图像的绘制&#xff0c;包括自行修改图像的属性&#xff0c;在绘制图像时会自动创建一个图形窗口来展现这些图像。本节内容继续讲讲这个&#xff08;Figure&#xff09;图像窗口即其一些常见用法。 其他python库链接…

AI生成思维导图和AI生成Excel公式

AI生成思维导图和AI生成Excel公式 AI 生成思维导图和 AI 生成 Excel 公式是一个完全免费的 AI 办公合集网站。 它完全免费&#xff0c;一个网站支持多个实用 AI 办公功能&#xff0c;包括&#xff1a;免费 AI Excel 公式生成器、输入 Excel 公式解释含义、AI Excel 助手、Exc…

java中的VO、DAO、BO、PO、DO、DTO

VO、DAO、BO 等对象在了解这里 po、vo、dao、之前先介绍下 MVC 开发模式M层负责与数据库打交道&#xff1b;C层负责业务逻辑的编写&#xff1b;V层负责给用户展示&#xff08;针对于前后端不分离的项目&#xff0c;不分离项目那种编写模版的方式&#xff0c;理解V的概念更直观&…

More Effective C++ 条款16:牢记80-20准则(Remember the 80-20 Rule)

More Effective C 条款16&#xff1a;牢记80-20准则&#xff08;Remember the 80-20 Rule&#xff09;核心思想&#xff1a;软件性能优化遵循帕累托原则&#xff08;Pareto Principle&#xff09;&#xff0c;即大约80%的性能提升来自于优化20%的关键代码。识别并专注于这些关键…

Java中对泛型的理解

一、泛型是什么&#xff1f;1. 定义&#xff1a; 泛型允许你在定义类、接口或方法时使用类型参数&#xff08;Type Parameter&#xff09;。在使用时&#xff08;如声明变量、创建实例时&#xff09;&#xff0c;再用具体的类型实参&#xff08;Type Argument&#xff09; 替换…

Redis开发06:使用stackexchange.redis库结合WebAPI对redis进行增删改查

一、接口写法namespace WebApplication1.Controllers.Redis {[ApiController][Route("/api/[controller]")]public class RedisService : IRedisService{private readonly IConnectionMultiplexer _redis;//StackExchange.Redis库自带接口public RedisService(IConne…

【前端教程】从零开始学JavaScript交互:7个经典事件处理案例解析

在网页开发中&#xff0c;交互性是提升用户体验的关键。JavaScript作为网页交互的核心语言&#xff0c;通过事件处理机制让静态页面"动"了起来。本文将通过7个经典案例&#xff0c;从简单到复杂&#xff0c;逐步讲解JavaScript事件处理的实现方法和应用场景。 案例1&…

内存模型(Memory Model)是什么?

内存模型(Memory Model)是什么? 内存模型是一个非常深刻且核心的计算机科学概念。 核心摘要 内存模型是一个契约或协议,它精确定义了: 一个线程对共享内存的写操作,如何以及何时对其他线程可见。 内存操作(读/写)可以被重新排序的程度。 它连接了硬件(CPU如何执行指令…

在 MyBatis 中oracle基本数值类型的 JDBC 类型映射

基本数值类型的 JDBC 类型Java 类型JDBC 类型 (jdbcType)说明int / IntegerINTEGER标准整数类型long / LongBIGINT大整数类型short / ShortSMALLINT小整数类型float / FloatFLOAT单精度浮点数double / DoubleDOUBLE双精度浮点数java.math.BigDecimalDECIMAL高精度小数&#xff…

Spring注解演进与自动装配原理深度解析:从历史发展到自定义Starter实践

目录 Spring注解发展史 Spring 1.X Spring 2.X Spring 2.5之前 Required Repository Aspect Spring2.5 之后 Spring 3.x ComponentScan Import 静态导入 ImportSelector ImportBeanDefinitionRegistrar EnableXXX Spring 4.x Spring 5.x 什么是SPI 自动装配…

第三届机械工程与先进制造智能化技术研讨会(MEAMIT2025)

【重要信息】 大会官网&#xff1a;https://www.yanfajia.com/action/p/BYE27DYDhttps://www.yanfajia.com/action/p/BYE27DYD 会议地点&#xff1a;哈尔滨理工大学 论文检索&#xff1a;EI Compendex、Scopus 还有部份版面&#xff0c;欲投稿从速&#xff0c;即将提交出版…

笔记本电脑频繁出现 vcomp140.dll丢失怎么办?结合移动设备特性,提供适配性强的修复方案

对于需要用电脑处理工作的人来说&#xff0c;“vcomp140.dll 丢失” 导致程序频繁闪退&#xff0c;无疑会严重影响工作效率。尝试重启电脑、重新安装软件后&#xff0c;问题依然存在&#xff0c;这时候该怎么办&#xff1f;别着急&#xff0c;vcomp140.dll 丢失看似棘手&#x…

微动开关-电竞鼠标核心!5000万次寿命微动开关评测

一、主流电竞微动开关技术对比‌光磁微动技术‌采用非接触式光学触发原理理论寿命突破5000万次触发响应速度0.2ms‌‌传统机械微动‌欧姆龙D2FC-F-7N系列5000万次标称寿命机械结构简单可靠‌‌创新结构微动‌双飞燕漆蓝荧光微动特殊涂层提升耐久性手感反馈独特‌二、5000万次寿…

Go语言与Docker 开发的核心应用领域

1. 容器化应用构建与部署‌‌轻量化镜像构建Go 语言编译生成静态二进制文件&#xff0c;结合多阶段构建的 Dockerfile&#xff0c;可大幅缩小镜像体积&#xff08;例如使用 scratch 或 alpine 基础镜像&#xff09;&#xff0c;提升部署效率‌。示例 Dockerfile 片段&#xff1…