C++函数三剑客:缺省参数·函数重载·引用的高效编程指南

news2025/5/19 16:39:33

前引:在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 = 10

    int& 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);

 二级指针函数的变化:

都需要传二级指针,它们的传参对象都指向同一个 (一级指针地址 与 引用对象同址),例如下面的 pcur同址

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;//修改方式1
	n++;

	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;
}

所以在使用引用做返回值时,需要特别注意该函数的生命周期,引用的使用是很活跃的! 

【雾非雾】期待与你下次相遇! 

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

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

相关文章

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…

机器学习 Day18 Support Vector Machine ——最优美的机器学习算法

1.问题导入&#xff1a; 2.SVM定义和一些最优化理论 2.1SVM中的定义 2.1.1 定义 SVM 定义&#xff1a;SVM&#xff08;Support Vector Machine&#xff0c;支持向量机&#xff09;核心是寻找超平面将样本分成两类且间隔最大 。它功能多样&#xff0c;可用于线性或非线性分类…

答题pk小程序道具卡的获取与应用

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

leetcode3265. 统计近似相等数对 I-medium

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

【架构篇】代码组织结构设计

代码组织结构设计&#xff1a;模块化分层与高效协作实践 摘要 本文以Java项目为例&#xff0c;解析后端代码组织的标准化结构&#xff0c;涵盖模块划分原则、依赖管理策略及实际应用场景。通过模块化设计提升代码可维护性、团队协作效率及系统扩展能力。 一、模块化设计的核心…

日期数据渲染转换问题

今天在学习Springboot框架时&#xff0c;想做一个非常简单的增删改查巩固一下&#xff0c;结果在数据渲染上出现了一个小问题&#xff0c;如图数据库中的数据一切正常 但是在前端渲染时&#xff0c;是下面这个效果 这是因为数据库存储的日期类型数据在前端渲染时&#xff0c;没…

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 编译帮助文档&#xff08;qch&#xf…

创建指定版本的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…

电子电路仿真实验教学平台重磅上线!——深圳航天科技创新研究院倾力打造,助力高校教学数字化转型

在传统电子电路课堂中&#xff0c;实验室的灯光总与高昂的成本、拥挤的设备、反复的耗材损耗相伴&#xff0c;而教师不得不面对这样的现实&#xff1a;有限的硬件资源束缚着教学深度&#xff0c;不可逆的实验风险制约着创新探索&#xff0c;固化的时空场景阻碍着个性化学习。当…

搭建一个WordPress网站需要多少成本

WordPress 最初可能只是一个简单的博客平台。但近年来&#xff0c;它不仅成为了最好的博客平台&#xff0c;还成为了一个全面的内容管理系统。白宫、jQuery、NGINX、《纽约时报》等企业都把 WordPress 作为自己的网上家园。 不过&#xff0c;它们只是其中的佼佼者。根据 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 在存储技术的演进历程中&#xff0c;美光科技的NC016、NC017、NC101与NC102系列固态芯片&#xff0c;凭借其技术创新与市场适应性&#xff0c;成为行业关注的焦点。本文将从技术内核、产品性能、行业动向、应用场景及市场价值五个维度&#…

[Android] 青木扫描全能文档3.0,支持自动扫描功能

声明&#xff1a;根据许多帖友的反馈&#xff0c;我也根据重新实测得出结论&#xff1a;该app是提供一天的体验时间&#xff0c;后续还是采取收费才能使用功能的措施。因为现在市面上免费使用的扫描工具很少了&#xff0c;所以当初我初步测试感觉软件不错就发布了出来&#xff…

通俗解释Transformer在处理序列问题高效的原因(个人理解)

Transformer出现的背景 CNN 的全局关联缺陷卷积神经网络&#xff08;CNN&#xff09;通过多层堆叠扩大感受野&#xff0c;但在自然语言处理中存在本质局限&#xff1a; 局部操作的语义割裂&#xff1a;每个卷积核仅处理固定窗口&#xff08;如 3-5 词&#xff09;&#xff0c;…

区间带边权并查集,XY4060泄露的测试点

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 码蹄集 二、解题报告 1、思路分析 关于带边权并查集&#xff1a;并查集&…

【数据结构】1-4算法的空间复杂度

数据结构知识点合集 知识点 空间复杂度的定义以及计算 空间复杂度--空间开销&#xff08;内存开销&#xff09;与问题规模 n 之间的关系 无论问题规模怎么变&#xff0c;算法运行所需的内存空间都是固定的常量&#xff0c;算法空间复杂度为S(n) O(1)&#xff0c;S 表示 “Spac…

OpenAI推出Codex — ChatGPT内置的软件工程Agents

OpenAI继续让ChatGPT对开发者更加实用。 几天前,他们增加了连接GitHub仓库的支持,可以"Deep Research"并根据你自己的代码提问。 今天,该公司在ChatGPT中推出了Codex的研究预览版,这是迄今为止最强大的AI编码Agent。 它可以编写代码、修复错误、运行测试,并在…

AI日报 · 2025年5月15日|GPT-4.1 登陆 ChatGPT

AI日报 2025年5月15日&#xff5c;GPT-4.1 登陆 ChatGPT 1、OpenAI 在 ChatGPT 全面开放 GPT-4.1 与 GPT-4.1 mini 北京时间 5 月 14 日晚&#xff0c;OpenAI 在官方 Release Notes 中宣布&#xff1a;专为复杂代码与精细指令场景打造的 GPT-4.1 正式加入 ChatGPT&#xff0…

W5500使用ioLibrary库创建TCP客户端

1、WIZnet全硬件TCP/IP协议栈 WIZnet全硬件TCP/IP协议栈,支持TCP,UDP,IPv4,ICMP,ARP,IGMP以及PPPoE协议。 以太网&#xff1a;支持BSD和WIZCHIP&#xff08;W5500/W5300/W5200/W5100/W5100S&#xff09;的SOCKET APIs驱动程序。 互联网&#xff1a; DHCP客户端 DNS客户端 FTP客…