NO.33十六届蓝桥杯备战|函数|返回值|声明|调用|引用|函数重载(C++)
返回值
我们在设计的函数的时候,函数在经过计算后,有时候需要带回⼀些计算好的数据,这时候往往使⽤return 来返回,这⾥我们就讨论⼀下使⽤ return 返回。
- return 后边可以是⼀个数值,也可以是⼀个表达式,如果是表达式则先执⾏表达式,再返回表达式的结果。函数返回的值,可以使⽤变量来接收,如果不需要这个返回值,也可以不接收。
// 这⾥使⽤简化版本的加法函数
int Add(int x, int y)
{ return x + y; // 1. 先执⾏x+y,得到该表达式计算的结果 2. 执⾏return,返回结果
}
//在main函数中使⽤return 0; 返回的就是⼀个数值
- return 后边也可以什么都没有,直接写 return; 这种写法适合函数返回类型是 void 的情况
void test(int n)
{ if(n == 2) return; //只要执⾏这⾥的return,函数就提前返回,不再打印数据 cout << n << endl;
}
- return 返回的值和函数返回类型不⼀致,系统会⾃动将返回的值的类型隐式转换为函数的返回类型
#include <iostream>
using namespace std;
int test()
{ return 3.14;
} int main()
{ int ret = test(); cout << ret << endl; return 0;
}
- return 语句执⾏后,函数就彻底返回,后边的代码不再执⾏。
#include <iostream>
using namespace std;
void print_arr(int arr[], int n)
{ int i = 0; for(i=0; i<n; i++) { if(i == 5) return;//对⽐换成break cout << arr[i] << " "; } cout << endl; cout << "打印完毕" << endl;
}
int main()
{ int arr[10] = {1,2,3,4,5,6,7,8,9,10}; print_arr(arr, 10); return 0;
}
函数的声明和调⽤
函数声明
⼀般在使⽤函数的⽅式写代码的时候,函数定义好之后,在后续的代码中对函数进⾏调⽤,例如 代码1 。有时候我们也可能将函数定义放在了函数调⽤的后边,例如 代码2 ,这时候编译器在编译的时候就会有警告出现(如下图),提⽰这个函数可能不存在,为了消除这种警告,我们⼀般在函数的调⽤之前先声明⼀下这个函数,这就是函数声明。函数声明就是告诉编译器,有⼀个函数名字叫什么,参数是什么,返回类型是什么,⾄于这个函数是否真的存在,是要看函数的定义了。函数调⽤必须满⾜先声明后使⽤。
//代码1
#include <iostream>
using namespace std;
//函数定义
int Add(int x, int y)
{ return x + y;
}
int main()
{ int a = 10; int b = 20; int c = Add(a, b); cout << c << endl; return 0;
}
//代码2
#include <iostream>
using namespace std;
//函数声明
int Add(int x, int y); int main()
{ int a = 10; int b = 20; int c = Add(a, b); cout << c << endl; return 0;
}
int Add(int x, int y) //函数定义
{ return x + y;
}
函数调⽤
函数调⽤的⽅式,⼀般会分为两类:传值调⽤和传址(引⽤)调⽤
传值调⽤
写⼀个函数Max,求两个整数的较⼤值
#include <iostream>
using namespace std;
int Max(int x, int y)
{ return x > y ? x : y;
}
int main()
{ int a = 0; int b = 0; cin >> a >> b; int c = Max(a, b); cout << c << endl; return 0;
}
第14⾏调⽤ Max 函数时,就是传值调⽤。传值调⽤就是将实参的数据直接传递给形参。这个过程其实是将实参的值拷⻉⼀份给 Max 函数使⽤,这份副本其实就是形参变量。这时形参和实参是不同的变量,所以对形参的修改,不会影响实参。这种情况下参数传递的⽅式只能从实参到形参,也就是单向传递。为了理解什么是单向传递,我们看⼀下案例2。
写⼀个函数Swap,交换两个整型变量的值。
#include <iostream>
using namespace std;
void Swap(int x, int y)
{ int z = x; x = y; y = z;
}int main()
{ int a = 0; int b = 0; cin >> a >> b; cout << "交换前, a = " << a << " b = " << b << endl; Swap(a, b); cout << "交换后, a = " << a << " b = " << b << endl; return 0;
}
运⾏程序你会发现,其实 Swap 函数中的 x 和 y 确实会交换,但是 main 函数的中的 a 和 b 其实没有交换。这就是值传递的特点,形参和实参是不同的内存空间,对形参的修改不会影响实参,数据仍然是单向传递的,所以交换的效果没有达到。
- 传值调⽤的⽅式在什么时候使⽤?
其实传值调⽤的⽅式⼀般应⽤的场景就是:仅需要通过传参的⽅式将实参的值传递给被调函数,被调函数就可以完成⼯作,⽽不需要改变实参的值。⽐如,案例1中的Max函数,将 a 和 b 的值传递给形参 x 和 y ,在 Max 函数中使⽤ x 和 y 来求较⼤值,就能得到 a 和 b 中的较⼤值。 - 如何改造 Swap 函数才能实现交换的效果呢?
这⾥可以使⽤指针,也可以使⽤引⽤。接下来我们讲⼀下C++中的引⽤。
引⽤
引⽤概念
引⽤不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,编译器不会为引⽤变量开辟内存空间,它和它引⽤的变量是同⼀块内存空间。
类型&引⽤变量名=引⽤实体;
void TestRef()
{ int a = 10; int& ra = a; // 定义引⽤类型 //通过printf输出a,ra的地址 printf("%p\n", &a); printf("%p\n", &ra);
}
引⽤特性
- 引⽤在定义时必须初始化
- ⼀个变量可以有多个引⽤
- 引⽤⼀旦引⽤⼀个实体,再不能引⽤其他实体
void TestRef()
{ int a = 10; // int& ra; // 该条语句编译时会出错 int& ra = a; int& rra = a; printf("%p %p %p\n", &a, &ra, &rra);
}
传址(引⽤)调⽤
#include <iostream>
using namespace std;
void Swap(int& x, int& y)
{ int z = x; x = y; y = z;
}
int main()
{ int a = 0; int b = 0; cin >> a >> b; cout << "交换前, a = " << a << " b = "<< b << endl; Swap(a, b); cout << "交换后, a = " << a << " b = "<< b << endl; return 0;
}
上⾯这种实现 Swap 函数实现⽅式就是函数的传引⽤调⽤。这种调⽤⽅式的本质是将实参变量的地址传递给了形参,⽽形参使⽤指针直接找到实参来进⾏操作。所以修改形参的时候,直接改变的就是实参,这就是引⽤的应⽤。
拓展学习:swap函数
其实在C++的STL中也提供了⼀个库函数 swap ,这个函数可以⽤来交换两个变量,也可以交换两个数组(容器的值),如果掌握了,我们就不需要⾃⼰再⾃⼰实现交换的逻辑,直接使⽤现成的函数。
swap 函数需要的头⽂件 <utility> 。
#include <iostream>
#include <utility>
using namespace std;
int main()
{ int a = 0; int b = 0; cin >> a >> b;cout << "交换前, a = " << a << " b = " << b << endl; swap(a, b);//直接使⽤库函数swap交换两个变量 cout << "交换后, a = " << a << " b = " << b << endl; return 0;
}
交换数组
#include <iostream>
#include <utility> //swap函数需要
using namespace std;
int main ()
{ int arr1[4]; // arr1: 0 0 0 0int arr2[] = {10,20,30,40}; // arr1: 0 0 0 0 arr2: 10 20 30 40swap(arr1, arr2); // arr1: 10 20 30 40 arr2: 0 0 0 0for (int e: arr1) cout << e << " "; cout << endl; return 0;
}
交换字符串
#include <iostream>
using namespace std;
void printString(string& s)
{ cout << s << endl;
}
int main()
{ string s("hello world"); printString(s);
}
传值、传引⽤效率⽐较
定义了⼀个全局字符串 s ,然后以传值和传引⽤的⽅式进⾏对⽐,看效率的差异
#include<iostream>
#include<ctime>
using namespace std;
//定义全局字符串s
string s("hello world");
void TestFunc1(string s) {}
void TestFunc2(string& s) {}
void Test()
{ // 以值作为函数参数 size_t begin1 = clock(); for (size_t i = 0; i < 10000000; ++i) { TestFunc1(s); } size_t end1 = clock(); // 以引⽤作为函数参数 size_t begin2 = clock(); for (size_t i = 0; i < 10000000; ++i) { TestFunc2(s); } size_t end2 = clock(); // 分别计算两个函数运⾏结束后的时间 cout << "TestFunc1(string)-time:" << end1 - begin1 << endl; cout << "TestFunc2(string&)-time:" << end2 - begin2 << endl;
}
int main()
{ Test(); return 0;
}
![![[Pasted image 20250309160724.png]]](https://i-blog.csdnimg.cn/direct/a7a31f16d91d4564afce049c69c01035.png)
采⽤传值调⽤过程中,函数传参,将实参传递给形参的时候,形参会创建新的空间,再将实参的数据给形参拷⻉⼀份;但是引⽤传参的⽅式,就不存在数据的拷⻉,只是在形参的部分建⽴引⽤的关系,形参就是实参。所以引⽤传参的效率要⾼于传值调⽤的⽅式。
数组在传参的时候,形参和实参本来就是同⼀个数组,所以数组传参的时候,不需要使⽤引⽤参数。
函数重载
重载概念
引⼊:
⽐如:我们现在要写⼀个函数,求两个整数的和,那么我们可以这么写
#include <iostream>
using namespace std;
int IntAdd(int x, int y)
{ return x + y;
}
int main()
{ int a = 0; int b = 0; cin >> a >> b; int c = IntAdd(a, b); cout << c << endl; return 0;
}
实现⼀个函数求两个 double 类型浮点数的和
double DoubleAdd(double x, double y)
{ return x + y;
}
那么上⾯的 IntAdd 和 DoubleAdd 函数的功能是类似的,都是完成求两个数的求和,只是参数类型有差异⽽已,既然功能是类似的,能不能函数名字统⼀⼀下都叫 Add() 呢?这样使⽤ Add() 函数的⼈,不需要记忆很多名字,就⽐较⽅便。这是C++中引⼊的函数重载的功能
函数重载:
C++中的函数重载(Function Overloading)是指在同⼀个作⽤域中可以有多个同名函数,它们的函数名称相同,但是参数列表不同。
函数返回类型 函数名(参数1, 参数2,...);
这⾥的“不同”指的是参数的数量、类型或顺序⾄少有⼀个不同。函数的返回类型并不影响函数的重载,因为C++编译器不会根据返回类型来区分不同的函数
重载举例
#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int a, int b)
{ return a + b;
}
double Add(double a, double b)
{ return a + b;
}// 2、参数个数不同
void f()
{ cout << "f()" << endl;
}
void f(int a)
{ cout << "f(int a)" << endl;
} // 3、参数类型顺序不同
void f(int a, char b)
{ cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{ cout << "f(char b, int a)" << endl;
} int main()
{ Add(10, 20); Add(10.1, 20.2); f(); f(10); f(10, 'a'); f('a', 10); return 0;
}
相关文章:
NO.33十六届蓝桥杯备战|函数|返回值|声明|调用|引用|函数重载(C++)
返回值 我们在设计的函数的时候,函数在经过计算后,有时候需要带回⼀些计算好的数据,这时候往往使⽤return 来返回,这⾥我们就讨论⼀下使⽤ return 返回。 return 后边可以是⼀个数值,也可以是⼀个表达式,…...
5G工业路由器赋能无人码头,港口物流智能化管理
全球贸易发展促使港口需提升运营效率,传统港口面临诸多难题,无人码头成为转型关键方向。5G 工业路由器为其提供有力通信支持,引领港口物流变革。 随着无人码头建设在全球兴起,如荷兰鹿特丹港、中国上海洋山港等。码头作业设备需实…...
机试准备第14天
首先进行树的学习。树的存储分为链式存储与顺序存储。完全二叉树是可以顺序存储的,将各个节点从上往下,从左往右存储。 第一题是找位置,好兄弟给的一道题,一遍过了。 #include <stdio.h> #include <map> #include &…...
【Academy】OAuth 2.0 身份验证漏洞 ------ OAuth 2.0 authentication vulnerabilities
OAuth 2.0 身份验证漏洞 ------ OAuth 2.0 authentication vulnerabilities 1. 什么是 OAuth?2. OAuth 2.0 是如何工作的?3. OAuth 授权类型3.1 OAuth 范围3.2 授权代码授权类型3.3 隐式授权类型 4. OAuth 身份验证4.1 识别 OAuth 身份验证4.2 侦察OAuth…...
有关Java中的多线程
学习目标 ● 掌握线程相关概念 ● 掌握线程的基本使用 ● 掌握线程池的使用 ● 了解解决线程安全方式 1.为什么要学习线程? ● 从1946年2月14日世界上第一台计算机在美国宾夕法尼亚大学诞生到今天,计算和处理的模式早已从单用户单任务的串行模式发展到了多用户多…...
【eNSP实战】配置交换机端口安全
拓扑图 目的:让交换机端口与主机mac绑定,防止私接主机。 主机PC配置不展示,按照图中配置即可。 开始配置之前,使用PC1 ping 一遍PC2、PC3、PC4、PC5,让交换机mac地址表刷新一下记录。 LSW1查看mac地址表 LSW1配置端…...
MAC-禁止百度网盘自动升级更新
通过终端禁用更新服务(推荐) 此方法直接移除百度网盘的自动更新组件,无需修改系统文件。 步骤: 1.关闭百度网盘后台进程 按下 Command + Space → 输入「活动监视器」→ 搜索 BaiduNetdisk 或 UpdateAgent → 结束相关进程。 2.删除自动更新配置文件 打开终端…...
LLMs基础学习(一)概念、模型分类、主流开源框架介绍以及模型的预训练任务
文章目录 LLM基础学习(一)一、大语言模型(LLMs)的简单介绍定义与基本信息核心特点局限性参考的模型 二、大语言模型(LLMs)名称后 “175B”“60B”“540B” 等数字的含义数字代表模型参数数量具体示例参数数…...
【leetcode hot 100 24】两两交换链表中的节点
解法一:先判断链表是否为空,若为空则直接返回;否则用left和right指向第一个和第二个节点,当这两个节点非空时一直执行交换。其中先判断right.nextnull,说明链表为偶数且已经交换完break;再判断right.next.n…...
软件IIC和硬件IIC的主要区别,用标准库举例!
学习交流792125321,欢迎一起加入讨论! 在学习iic的时候,我们经常会遇到软件 IC和硬件 IC,它两到底有什么区别呢? 软件 IC(模拟 IC)和硬件 IC(外设 IC)是两种实现 IC 总线通信的方式…...
Codeforces Round 1006 Div3 A-E
A 题目描述 夏目章人(Natsume Akito)刚刚在一个新世界苏醒,便立即收到了他的第一个任务!系统为他提供了一个包含 n 个零的数组 a,以及两个整数 k 和 p。在每次操作中,章人需要选择两个整数 i 和 x&#x…...
4个 Vue 路由实现的过程
大家好,我是大澈!一个喜欢结交朋友、喜欢编程技术和科技前沿的老程序员👨🏻💻,关注我,科技未来或许我能帮到你! Vue 路由相信朋友们用的都很熟了,但是你知道 Vue 路由…...
git文件过大导致gitea仓库镜像推送失败问题解决(push failed: context deadline exceeded)
问题描述: 今天发现gitea仓库推送到某个镜像仓库的操作几个月前已经报错终止推送了,报错如下: 首先翻译报错提示可知是因为git仓库大小超过1G限制。检查本地.git文件,发现.git文件大小已达到1.13G。确定是.git文件过大导致&…...
简要分析NETLINK_ROUTE参数
NETLINK_ROUTE时Linux内核中Netlink协议族的一个子类型,专用于用户空间与内核网络子系统之间的通信,它是实现动态网络配置(如路由表、网络接口、地址管理)的核心机制,为现代网络管理工具(如iproute2&#x…...
Java中default关键字
1. 在 switch 语句中作为默认分支 在 switch 语句里,default 用于定义当所有 case 标签的值都无法匹配 switch 表达式的值时要执行的代码块。它并非强制要求,但使用它可以增强代码的健壮性,处理未预见的情况。 public class SwitchDefaultE…...
怎么利用DeepSeek进行PCB设计?
最近在琢磨利用Deepseek改善PCB的细节设计,毕竟立创EDA里面没有集成DS,因此,如何让DS能识别图片成了重中之重。所幸最近腾讯元宝里面集成了R1的满血版,这个版本可以上传图片,于是让DS识别图片就可能了。 在原理图设计…...
详细介绍 Jupyter nbconvert 工具及其用法:如何将 Notebook 转换为 Python 脚本
nbconvert 是 Jupyter 提供的一个非常强大的工具,允许用户将 Jupyter Notebook 文件(.ipynb)转换成多种格式,包括 Python 脚本(.py)、HTML、PDF、LaTeX 等。你可以通过命令行来运行 nbconvert,也…...
windows上传uniapp打包的ipa文件到app store构建版本
uniapp是一个跨平台的框架,使用windows电脑也可以开发ios软件,因为uniapp的打包是在云端实现的,本地电脑无需使用mac电脑即可完成打包。 但是打包后的ipa文件需要上架到app store的构建版本上,没有mac电脑,又如何上架…...
PySide(PyQT),QGraphicsItem的pos()和scenePos()区别
在QGraphicsItem中,pos()和scenePos()是两个重要的方法,用于描述图形项的位置,但它们的含义和用途有所不同。理解它们的区别对于正确操作和管理QGraphicsItem的位置至关重要。 1. pos()方法 • 定义:pos()返回的是QGraphicsItem在…...
idea 快捷键 Reformat code
Reformat code...
Spring Boot 项目中使用责任链模式实现复杂接口解耦和动态编排(带示例)
目录 责任链模式概述 解耦 动态编排 运用场景 代码示例 1. 定义请求和响应对象 2. 定义处理者接口和抽象处理者类 3. 实现具体的处理者类 4. 配置责任链 5. 控制器类调用责任链 代码解释 责任链模式概述 责任链模式是一种行为设计模式,它允许你将请求沿着处理者链…...
消防设施操作员考试备考:以技巧为翼,翱翔知识天空
消防设施操作员考试的备考过程中,掌握实用技巧能让学习事半功倍。以下为您介绍一系列备考技巧,助您在知识的天空中自由翱翔。 记忆技巧:化繁为简 消防知识众多,记忆难度较大。可以采用多种记忆方法,如口诀记忆法…...
qt之No executable specified
在Qt中遇到文件复制操作时出现“No executable specified”错误,通常与程序编译或运行环境配置问题相关,而非文件操作本身的问题。以下是可能的原因及解决方案: 项目配置文件损坏 现象: 在执行文件操作前,程序无法启动…...
物联网商业模式
物联网商业模式是一种战略规划,它融合了物联网技术来创造价值并获取收入。它与传统商业模式的不同之处在于,它利用互联设备来改善运营、提升客户体验以及优化服务项目。在当今由科技驱动的世界中,这种商业模式通过利用实时数据来提供创新服务…...
解决ElementPlus对话框el-dialog中关闭事件重复触发问题
问题背景 在使用ElementPlus的el-dialog组件时,发现点击取消按钮会触发两次关闭事件: 1. 第一次参数为PointerEvent(事件对象) 2. 第二次参数为undefined 需要确保点击取消按钮时仅触发一次有效关闭事件,并传递正确…...
【RabbitMQ】事务
事务的简单配置及使用 配置事务管理器声明队列生产者代码测试 RabbitMQ是基于AMQP协议实现的,该协议实现了事务机制,因此RabbitMQ也支持事务机制. SpringAMQP也提供了对事务相关的操作.RabbitMQ事务允许开发者确保消息的发送和接收是原子性的,…...
算法刷题--贪心算法
要点 其实也没啥要点,就是求局部最优解,完事了将局部最优解汇总、筛选、max\min之类的,获得全局最优解,每一次都选择最优的,这个就是贪心算法。 例题 分发饼干-中等 大概就是一堆小孩g,每个人都有一个胃口g[i]&…...
MVCC的理解(Multi-Version Concurrency Control,多版本并发控制)
1.事务特性(ACID) 原子性:事务要么全部成功,否则全部回滚 一致性:保证逻辑完整性(关联表删除) 隔离性:事务并发隔离(行锁,间隙锁) 持久性:已提交的事务永…...
CCF-CSP第24次认证第2题 --《序列查询新解》
4281. 序列查询新解 - AcWing题库 上一题“序列查询”中说道: A[A0,A1,A2,⋯,An]A[A0,A1,A2,⋯,An] 是一个由 n1n1 个 [0,N)[0,N) 范围内整数组成的序列,满足 0A0<A1<A2<⋯<An<N0A0<A1<A2<⋯<An<N。 基于序列 AA&#…...
Webpack 打包详细教程
Webpack 是一个现代 JavaScript 应用的静态模块打包工具,它可以处理 JavaScript、CSS、图片等资源,并优化它们以提高性能。以下是 Webpack 从基础到进阶的详细教程。 1. Webpack 基础概念 Webpack 的核心概念包括: Entry(入口&a…...
