C++函数三剑客:缺省参数·函数重载·引用的高效编程指南
前引:在C++编程中,缺省参数、函数重载、引用是提升代码简洁性、复用性和效率的三大核心机制。它们既能减少冗杂的代码,又能增强接口设计的灵活性。本文将通过清晰的理论解析与实战案列,带你深入理解这三者的设计思想、使用场景以及闭坑指南~
【注:由于内容平均排版,引用的结尾特安排在下一篇!】
目录
缺省参数
何为缺省参数
全缺省参数
半缺省参数
不缺省参数
注意
函数重载
何为函数重载
参数个数不同
参数类型不同
类型顺序不同
注意
为何C++支持函数重载,而C不支持
引用
什么是引用
引用的使用
一级指针的变化:
二级指针的变化:
编辑
语法注意:
一级指针函数的变化:
二级指针函数的变化:
编辑编辑
语法注意:
引用的指针的优劣
优先使用引用的场景:
必须使用指针的场景:
关于引用返回值的讲解
缺省参数
何为缺省参数
允许函数在声明时指定默认值,调用函数时可以省略部分参数。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。例如:
Func();//没有传参使用参数的默认值
Func(10);//传参了使用指定的参数
全缺省参数
顾名思义,全缺省参数就是所有参数全部都额外指定,例如:
Func();Func(1,2,3);//与参数个数无关
半缺省参数
半缺省位于全缺省 和 不缺省之间,也比较好理解,比如:
Func();
Func(1,3);(与参数个数无关)
不缺省参数
所有参数都不额外指定,例如:
Func(1,2,3);//缺不缺省与参数个数无关
Func(1,2);
Func(1);
注意
这样看来我们的参数指不指定似乎是随机的!但是,它有语法规则限制:
默认参数必须从右往左连续设置(默认参数可以是常量、全局变量、函数返回值....但不能是局部变量),例如:
参数必须从右往左连续设置的几种情况:
(1)传参顺序错误
(2)函数参数顺序错误
(3)声明与定义只能选择一个设置函数缺省,否则就会报错
(4)缺省只有.cpp文件支持,在纯c的.c文件中不支持
函数重载
何为函数重载
是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题
参数个数不同
参数个数指的是传参的个数,不是函数接收的参数
参数类型不同
函数参数接收的类型可以不同,例如:
void Func(int a=5,int b=10,int c=10)
{std::cout << a + b + c << std::endl;
}void Func(double a = 5, double b = 10, double c = 10)
{std::cout << a + b + c << std::endl;
}
同时,参数类型可以不用统一,只要保证函数名相同就行,例如:
void Func(int a=5,int b=10,int c=10)
{std::cout << a + b + c << std::endl;
}void Func(double a = 5, double b = 10, double c = 10)
{std::cout << a + b + c << std::endl;
}void Func(double a = 5, double b = 10, int c = 10)
{std::cout << a + b + c << std::endl;
}
类型顺序不同
这点其实和刚才的参数类型不同很相似,我们直接看:
void Func(double a=5,int b=10,int c=10)
{std::cout << a + b + c << std::endl;
}void Func(double a = 5, double b = 10, int c = 10)
{std::cout << a + b + c << std::endl;
}
注意
(1)需要注意的是,函数传参跟声明个数是匹配的
比如它不会去自动识别你想匹配哪个函数。两个函数传参,对应两个函数接收
(2)如果只有返回值不同是不构成重载的,因为编译器无法根据参数是判断是不是构成重载
为何C++支持函数重载,而C不支持
首先不论是C还是C++,从代码->展示效果都会经历这几个阶段:
既然这个过程是一样的,那么它们之间必定在某个阶段有所差别:
小编认为可以这么总结:
假如我现在缺钱,想找某个人借,那么C借给我 跟 C++借给我的方式是不一样的!
在C中的编译阶段,根据函数定义直接兑现承诺,根据函数定义直接去替换成对应的函数,那么当再次调用这个函数,发现跟之前的不一样了,就会报错。比如 C 直接借给你钱!
在C++中的编译阶段,根据函数声明先承诺,根据函数的声明生成不同的函数类型,因此可以存在多个同名的函数,此时同名不代表是同一个函数。C++ 会先答应借给你,并不是直接借给你钱!
引用
什么是引用
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空 间,它和它引用的变量共用同一块内存空间
引用是可以赋值给变量的,俗称为“引用变量”,例如:从可以赋值来看,我们看到 pc 并不是指针
int tmp = 10;int& pc = tmp;
int cur = pc;
形象比喻:比如李逵,江湖上叫“黑旋风”,他也叫“铁牛”,这三个称呼是同一个人,你叫其中的某一个称呼,叫的其实是同一个对象
引用的使用
学了C++中的引用之后,你会发现C++中的指针使用与C中的指针使用有很大的变化,更简洁
例如常见的几种C中指针用法:
C++中学了引用之后,我们可以这么改进,下面我们分开对比,否则不好理解!
一级指针的变化:
//设置变量int tmp = 10int& cur = tmp;//C++cur = 30;;
我们可以看到,C++引用到一级指针中去,可以不用去解引用了,直接通过变量访问
二级指针的变化:
在C中我们的二级指针是指向一级指针地址的
在C++引用中,引用的对象同样是一级指针,不是变量本身哦!(牢记),例如:
//二级指针引用int*& coun = p;//C++*coun = 100;
解释:coun是p的引用二者地址相同,操作的也就是p,*coun操作的也就是*p,*p也就是tmp本身
这里需要注意:C++二级指针引用还是需要指向一级指针,因为二级指针的定义是:二级指针指向一级指针地址 ,只是这里不需要去给 p 加上取地址
语法注意:
C指针:
(1)可以不对指针进行初始化,但是有野指针的风险
(2)可以对指针进行赋值,比如为 NULL,或者指向其它变量或指针
(3)使用时操作变量需要解引用*,在函数里面->才能访问成员
例如:
//可以不初始化
int* p;
//可以赋值
int* p = NULL;
//需要解引用访问
*p = 20;
C++引用:
(1)必须初始化,且绑定后不可以重新绑定
(2)无空引用,始终指向有效的对象
(3)直接通过引用名访问,无需解引用
例如:
int tmp = 10;//必须初始化int& pc = tmp;//无空引用,始终指向有效对象int& cur = NULL;//直接通过引用名访问,无需解引用pc = 20;
一级指针函数的变化:
首先是传参,传指向对象 或者 指针命名对象都是可以的,它们的接收参数形式是统一的
就仿佛:我给“铁牛”沏一杯茶,和我给“黑旋风”沏一杯茶,对象是同一个人
Func(pc);Func(tmp);
二级指针函数的变化:
都需要传二级指针,它们的传参对象都指向同一个 (一级指针地址 与 引用对象同址),例如下面的 p 与 cur同址
Func(cur);Func(p);
语法注意:
(1)强制初始化,且无法为空,杜绝引用错误
//杜绝为空
int& pc;//必须绑定对象
int tmp;
int& cur = tmp;
(2)严格匹配类型,无法隐式转换
int tmp = 10;
//严格匹配类型,无法隐式转换
double& pc = tmp;
(3)C++引用二级指针需要指向一级指针,这个一级指针不能是C++引用类型
//设置变量
int tmp = 10;//一级指针
int* pc = &tmp;
int& cur = tmp;//二级指针
//不能使用C++一级指针引用对象
int*& pc = cur;//错误语法
int*& pc = pc;//正确语法
引用的指针的优劣
两者在运行性能上几乎一致,但引用通过语法减少了潜在的错误,提高了代码的健壮性
(1)引用概念上定义一个变量的别名,指针存储一个变量地址
(2)引用在定义时必须初始化,指针没有要求
(3)引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何 一个同类型实体
(4)没有NULL引用,但有NULL指针
(5)在 sizeof 中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数 (32位平台下占4个字节)
(6)引用自加即引用的实体增加 1 ,指针自加即指针向后偏移一个类型的大小
优先使用引用的场景:
(1)函数参数传递
(2)操作符重载
(3)返回值
必须使用指针的场景:
(1)动态内存管理
(2)与C库交互,比如调用 printf 或C标准库函数时
(3)可选参数或者多态
关于引用返回值的讲解
首先我们看一个错误例子,这是将一个引用变量赋值给另一个变量 ret:
首先:这里的打印虽然是“1”,但是它的打印值其实是不固定的,有以下两种情况:
(1)如果Func函数结束,栈帧销毁,没有清理栈帧,那么 ret 的结果侥幸是正确的
(2)如果Func函数结束,栈帧销毁,,清理了栈帧,那么 ret 的结果就是随机的
例如下面:普通函数可以通过中间变量赋值带回,引用没有中间变量,销毁了也就无法返回值了
我们的解决方案有以下两种:
(1)使用全局变量 或 静态变量,如:int n -> static int n
原因:当使用 static 修饰局部变量时,变量的周期会持续到整个程序结束,即函数调用完也不会 被销毁
int& Func()
{static int n = 0;//修改方式1n++;return n;
}int main()
{int ret = Func();std::cout << ret << std::endl;return 0;
}
(2)改返回值,而非引用,如:int& Func()-> int Func()
原因:修改之后只是一个简单的赋值,不与引用规则发生冲突
int Func()//修改方式2
{int n = 0;n++;return n;
}int main()
{int ret = Func();std::cout << ret << std::endl;return 0;
}
所以在使用引用做返回值时,需要特别注意该函数的生命周期,引用的使用是很活跃的!
【雾非雾】期待与你下次相遇!
相关文章:

C++函数三剑客:缺省参数·函数重载·引用的高效编程指南
前引:在C编程中,缺省参数、函数重载、引用是提升代码简洁性、复用性和效率的三大核心机制。它们既能减少冗杂的代码,又能增强接口设计的灵活性。本文将通过清晰的理论解析与实战案列,带你深入理解这三者的设计思想、使用场景以及闭…...
ORACLE 11.2.0.4 数据库磁盘空间爆满导致GAP产生
前言 昨天晚上深夜接到客户电话,反应数据库无法正常使用,想进入服务器检查时,登录响应非常慢。等两分钟后进入服务器且通过sqlplus进入数据库也很慢。通过检查服务器磁盘空间发现数据库所在区已经爆满,导致数据库在运行期间新增审…...
面试题总结一
第一天 1. 快速排序 public class QuickSort {public static void quickSort(int[] arr, int low, int high) {if (low < high) {// 分区操作,获取基准元素的最终位置int pivotIndex partition(arr, low, high);// 递归排序基准元素左边的部分quickSort(arr, …...

SWUST数据结构下半期实验练习题
1068: 图的按录入顺序深度优先搜索 #include"iostream" using namespace std; #include"cstring" int visited[100]; char s[100]; int a[100][100]; int n; void dfs(int k,int n) {if(visited[k]0){visited[k]1;cout<<s[k];for(int i0;i<n;i){i…...
专业版降重指南:如何用Python批量替换同义词?自动化操作不香嘛?
还在手动一个个改词降重?👀 是兄弟就别再CtrlF了,来试试Python自动同义词替换批量降重法,简直是论文改写效率神器! 这篇我们来一波实操干货: 👉 如何用Python写出一个自动替换论文关键词的脚本…...
一:操作系统之操作系统结构
深入浅出:一文读懂操作系统的五种核心结构 操作系统,作为计算机硬件与应用软件之间的桥梁,其内部组织结构是决定其性能、稳定性、可维护性和安全性的关键。就像建造房屋需要选择不同的建筑结构一样,设计操作系统也需要选择或混合…...

机器学习 Day18 Support Vector Machine ——最优美的机器学习算法
1.问题导入: 2.SVM定义和一些最优化理论 2.1SVM中的定义 2.1.1 定义 SVM 定义:SVM(Support Vector Machine,支持向量机)核心是寻找超平面将样本分成两类且间隔最大 。它功能多样,可用于线性或非线性分类…...
IIS入门指南:原理、部署与实战
引言:Web服务的基石 在Windows Server机房中,超过35%的企业级网站运行在IIS(Internet Information Services)之上。作为微软生态的核心Web服务器,IIS不仅支撑着ASP.NET应用的运行,更是Windows Server系统管…...
Linux运维——Shell脚本读取配置文件
Shell脚本读取配置文件 一、键值对格式配置文件(最常用)1.1、配置文件示例1.2、source命令导入1.3、sed解析1.4、解析数组 二、INI格式配置文件1.1、配置文件示例1.2、sed解析1.3、ini配置带数组(显式声明数组)1.4、ini配置带数组…...

答题pk小程序道具卡的获取与应用
道具卡是答题PK小程序中必不可少的一项增加趣味性的辅助应用,那么道具卡是如何获取与应用的呢,接下来我们来揭晓答案: 一、道具卡的获取: 签到获取:在每日签到中签到不仅可获得当日的签到奖励积分,同时连…...

leetcode3265. 统计近似相等数对 I-medium
1 题目:统计近似相等数对 I 官方标定难度:中 给你一个正整数数组 nums 。 如果我们执行以下操作 至多一次 可以让两个整数 x 和 y 相等,那么我们称这个数对是 近似相等 的: 选择 x 或者 y 之一,将这个数字中的两个…...

【架构篇】代码组织结构设计
代码组织结构设计:模块化分层与高效协作实践 摘要 本文以Java项目为例,解析后端代码组织的标准化结构,涵盖模块划分原则、依赖管理策略及实际应用场景。通过模块化设计提升代码可维护性、团队协作效率及系统扩展能力。 一、模块化设计的核心…...
2_Spring【IOC容器中获取组件Bean】
Spring中IOC容器中获取组件Bean 实体类 //接口 public interface TestDemo {public void doSomething(); } // 实现类 public class HappyComponent implements TestDemo {public void doSomething() {System.out.println("HappyComponent is doing something...")…...

日期数据渲染转换问题
今天在学习Springboot框架时,想做一个非常简单的增删改查巩固一下,结果在数据渲染上出现了一个小问题,如图数据库中的数据一切正常 但是在前端渲染时,是下面这个效果 这是因为数据库存储的日期类型数据在前端渲染时,没…...
Spring Boot拦截器详解:原理、实现与应用场景
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 一、拦截器概述 拦截器(Interceptor)是Spring MVC框架中用于对请求进行预处理和后处理的组件,主要作用于Controller层。相…...

ubuntu18.04编译qt5.14.2源码
ubuntu18.04编译qt5.14.2源码 文章目录 ubuntu18.04编译qt5.14.2源码[toc]1 前言2 参考文档3 下载源码3.1 方法13.2 方法23.3 方法3 4 ubuntu编译qt源码4.1 环境准备4.2 设置交换分区大小4.3 编译源码4.4 添加环境变量4.5 验证编译结果4.6 编译帮助文档(qch…...

创建指定版本的vite项目
1、获取vite的版本号 npm view create-vite versions 注:4.4.1版本即对应着node16版本的项目 2、创建制定版本的vite项目 npm init vite<version>...

iOS 初识RunLoop
iOS 初识RunLoop 文章目录 iOS 初识RunLoopRunLoop的概念RunLoop的功能RunLoop和线程的关系RunLoop的结构ModeObserverTimer 和 source小结 RunLoop的核心RunLoop的流程RunLoop的应用AutoreleasePool响应触控事件刷新界面常驻线程网络请求NSTimer 和 CADisplayLinkNSTimerGCDTi…...

电子电路仿真实验教学平台重磅上线!——深圳航天科技创新研究院倾力打造,助力高校教学数字化转型
在传统电子电路课堂中,实验室的灯光总与高昂的成本、拥挤的设备、反复的耗材损耗相伴,而教师不得不面对这样的现实:有限的硬件资源束缚着教学深度,不可逆的实验风险制约着创新探索,固化的时空场景阻碍着个性化学习。当…...

搭建一个WordPress网站需要多少成本
WordPress 最初可能只是一个简单的博客平台。但近年来,它不仅成为了最好的博客平台,还成为了一个全面的内容管理系统。白宫、jQuery、NGINX、《纽约时报》等企业都把 WordPress 作为自己的网上家园。 不过,它们只是其中的佼佼者。根据 Built…...

Python数据可视化 - Pyecharts绘图示例
文章目录 一、Pyecharts简介及安装1. Pyecharts简介2. 安装Pyecharts 二、准备数据三、饼图示例1. 初始化选项配置2. 饼图相关设置3. 全局配置项3.1 标题配置项3.2 图例配置项3.3 提示框配置项3.4 工具箱配置项3.5 视觉映射配置项 4. 系列配置项4.1 标签选项配置4.2 图元样式配…...

NC016NC017美光固态芯片NC101NC102
NC016NC017美光固态芯片NC101NC102 在存储技术的演进历程中,美光科技的NC016、NC017、NC101与NC102系列固态芯片,凭借其技术创新与市场适应性,成为行业关注的焦点。本文将从技术内核、产品性能、行业动向、应用场景及市场价值五个维度&#…...

[Android] 青木扫描全能文档3.0,支持自动扫描功能
声明:根据许多帖友的反馈,我也根据重新实测得出结论:该app是提供一天的体验时间,后续还是采取收费才能使用功能的措施。因为现在市面上免费使用的扫描工具很少了,所以当初我初步测试感觉软件不错就发布了出来ÿ…...
Vue 3 动态 ref 的使用方式(表格)
一、问题描述 先给大家简单介绍一下问题背景。我正在开发的项目中,有一个表格组件,其中一列是分镜描述,需要支持视频上传功能。用户可以为每一行的分镜描述上传对应的视频示例。然而,在实现过程中,出现了一个严重的问…...
Bash fork 炸弹 —— :(){ :|: };:
🧠 什么是 Fork 炸弹? Fork 炸弹是一种拒绝服务(DoS)攻击技术,利用操作系统的 fork() 系统调用不断创建新进程,直到系统资源(如进程表、CPU、内存)被耗尽,从而使系统无法…...
互联网大厂Java面试:从Spring Boot到微服务架构的技术深挖
场景描述 在某互联网大厂的面试会议室里,严肃的面试官老王正审视着面前的程序员明哥。这场面试以业务场景为切入点,围绕Java技术栈展开。 第一轮:基础知识与Spring生态 面试官老王: 明哥,你对Spring Boot的核心功能…...
IT审计之外包
外包管理的定义与重要性 外包管理是指企业将部分业务或服务委托给外部供应商进行管理和执行的过程。在IT领域,外包管理尤为重要,因为IT系统的复杂性和关键性要求企业必须确保外包服务的质量和安全性。外包管理不仅涉及合同管理,还包括供应商…...
精益数据分析(66/126):技术驱动的大规模用户调研——从工具组合到高效验证
精益数据分析(66/126):技术驱动的大规模用户调研——从工具组合到高效验证 在创业的移情阶段,如何突破小规模访谈的局限,快速获取大规模用户反馈?今天,我们结合LikeBright的实战案例与《精益数…...

通俗解释Transformer在处理序列问题高效的原因(个人理解)
Transformer出现的背景 CNN 的全局关联缺陷卷积神经网络(CNN)通过多层堆叠扩大感受野,但在自然语言处理中存在本质局限: 局部操作的语义割裂:每个卷积核仅处理固定窗口(如 3-5 词),…...
第12章 Java多线程机制
12.1 进程与线程 4种状态:新建、运行、中断和死亡。 (新建、运行、中断和死亡) 建立线程的两种方法:用Thread类或其子类。 线程新建后,必须调用 start () 方法使其进入就绪队列,才有机会获得 CPU 资源&a…...