高效学 C++|函数参数的引用传递和函数重载

news2024/11/15 8:24:25

 在节前拜读张哥dvlinker的博客_CSDN博客-VC++常用功能代码封装,C++相关,C++软件调试与异常排查从入门到精通系列教程领域博主的C++专栏后,毅然决然,想在春节期间系统的学习下C++入门知识,本文算是学习过程的小结及感悟!

C++语言中函数的声明形式如下:

返回值类型 函数名(参数表);

如声明将两个整型参数相加的函数add()的程序如下:

int add(int x, int y);

下面从函数参数的引用传递、函数重载两个方面介绍C++语言中的函数。

01、引用传递

引用是一种特殊的声明,可以用来限定变量的类型。如果在声明一个变量的同时将它声明为另一个变量的引用,则意味着这两个变量等同于一个变量,即声明为引用的变量是它所引用的变量的别名。下面的程序中将变量ri声明为变量i的引用。

int i = 0, j = 1;
int & ri = i; //ri是一个int类型的引用,它引用的变量是int类型的i
ri = 10; //相当于i = 10
ri = j; //相当于i = j

使用引用时必须注意下面两个问题。

(1)定义一个引用时,必须同时对它初始化,即明确它所引用的变量。

(2)引用类型的变量所引用的那个变量只能在初始化时指定,指定之后不能修改(实际上也没法修改)。

实际上,编译器对引用类型的变量自动地按照指针常量的形式进行了变换,编译器变换上面声明引用变量ri的语句如下:

int * const ri = &i;

这样,就可以很清楚地看到ri是一个常变量,该常变量是一个指针常量,并且该指针指向一个int型数据。因为ri是常变量,所以声明时必须要初始化,也因此不能在声明之后修改它的值。这就很好地解释了为什么对引用类型的变量有前面两条的限制。

同理,编译器将前面给引用变量ri赋值的语句自动地改写为:

*ri = 10;
*ri = j;

综上,编译器把“引用”改成了“指针”,所做的变换如下:

(1)将引用运算符“&”转换成指针运算符“* const”。

(2)在定义引用类型的变量时对右值取地址。

(3)对于函数的形参,如果它是引用类型,则形实结合时对实参取地址。

(4)对于使用引用变量的语句,在引用变量前加“*”。

总之,编译器自动地把“引用”改成了“指针常量”。

使用引用类型可使程序变得简洁、容易理解。使用引用类型的形参如例1所示。在该例中,swap函数完成两个数据的交换:函数中是交换形参的值,但由于形参是引用类型,所以实际上完成了实参的交换。在本例中,交换前变量x等于5,变量y等于10;交换后变量x等于10,变量y等于5。

【例1】 使用引用类型的形参。

1.  #include<iostream>
2.  using namespace std;
3.  void swap(int & a, int& b)
4. {
5.     int t;
6.     t = a;
7.     a = b;
8.     b = t;
9.  }

10.  int main()
11. {
12.     int x(5), y(10);
13.     cout << "x = " << x << " y = " << y <<endl;
14.     swap(x,y);
15.     cout << "x = " << x << " y = " << y <<endl;
16.     return 0;
17.  }

例2说明了函数返回引用类型的情况,此时可直接给函数调用后的返回值赋新值:变量x和变量y的初值分别是2和5;在调用了larger()函数之后给其返回值加5,由于变量y的初值较大且larger()函数的形参和返回值都是引用类型,所以实现了将变量y的值增5的功能,因此程序最后一行的输出为“x = 2 y = 10”。

【例2】 函数返回引用类型。

1.  #include<iostream>
2.  using namespace std;
3.  int & larger(int & a, int & b)
4.  {
5.     return a > b ? a : b;
6.  }
7.  int main()
8. {
9.     int x = 2, y = 5;
10.     cout << "x = " << x << " y = " << y <<endl;
11.     cout << (larger(x, y) += 5) << endl;
12.     cout << "x = " << x << " y = " << y <<endl;
13.     return 0;
14.  }

 函数返回引用类型的数据是经常用到的,因为返回值经常需要作为左值。需要注意的是,不能将非静态局部变量按引用类型返回,因为在函数返回后,该局部变量已经不存在了,从而返回值也不能作为左值。比如例2.3中,将larger()函数改为如下形式时将会出现警告。

int & larger(int & a, int & b)
{
   int i = a > b ? a : b;
   return i; //因为i为局部变量且返回值为引用类型,所以编译时会有警告
}

两种使用引用传递的主要情形如下:

(1)用于传递大量数据。因为引用传递被自动转换为指针传递,这能够减少复制数据的开销。

(2)用于返回一个内存空间作为左值。比如上面的larger()函数,为了能够给其返回值赋值,需要使用引用(或采用相应的指针形式,但比较麻烦)。

02、函数重载

在面向对象程序设计中,成员函数是对类的行为的描述。对于同一个类,存在这样一种情况:虽然它执行的动作的称谓是相同的,但在不同的情况下执行的过程却是不同的。对于普通的函数也是如此。比如,已知两个数,要求把它们加起来。此时,如果这两个数是整数,那么可以用整数的加法运算完成计算;如果已知的数是虚数,那么可以用虚数的加法运算来完成计算。对于这样的“把两个数相加”的要求,可以把它们抽象成函数。不过,由于执行过程不同,在C语言中需要使用不同的函数名来完成,如下面的函数声明所示(假设complex是已定义好的表示虚数的类型)。

int add_int(int a, int b);
complex add_complex(complex a, complex b);

显然,这样设计不利于阅读和使用。为解决此类问题,在C++语言中引入了函数重载的概念,即允许声明同名的函数。对于一个函数调用,编译器根据实参和形参的类型、个数及顺序自动确定调用哪个同名函数。比如上面两个函数可重新声明如下:

int add(int a, int b);
complex add(complex a, complex b);

在调用函数时,根据实参的类型来选择调用哪个函数:如果实参是整型,则调用第一个函数版本;如果实参的类型是虚数,则调用第二个函数版本。

实际上,编译器在编译C++语言的源程序时自动重命名了重载函数,重命名的方式大致是函数名加上参数类型列表,如上面两个函数会被重命名为类似于下面的形式。

int add_int_int(int a, int b);
complex add_complex_complex(complex a, complex b);

而对于调用语句“add(1, 2);”则会自动变为“add_int_int(1, 2);”。通过这种方式,编译器能够确定需要调用函数的哪个重载形式。

从上面的程序也可看出,在使用函数重载时要注意:尽管函数名可以相同,但形参的类型、个数及顺序一定要有不同,否则编译器就无法确定到底该调用哪个函数了。另外,函数的返回值类型不能用来区分函数的重载形式,因为在调用函数时常常不关心返回值,从而编译器也无法利用返回值的类型来确定该调用哪个函数。示例程序如下:

int   add(int x, int y){ ... } //第一个函数
float add(float x, float y){ ... } //参数类型不同,与第一行的函数构成重载
int   add(int x, int y, int z){ ... } //参数个数不同,与前两行的函数构成重载
int   add(int a, int b){ ... } //与第一行的函数只是形参名不同,重载出错
void  add(int x, int y){ ... } //不以返回值区分函数,重载出错

 

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

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

相关文章

pytorch深度学习一机多显卡训练设置,流程

最近在学习在服务器的ubuntu环境上配置用多个显卡训练&#xff0c;之前只用一个显卡训练实在是太慢了点 先看看服务器上有几个显卡&#xff1a; nvidia-smi即可得到具体的显卡信息&#xff1a; 每个显卡之前有对应的编号。 然后得知自己服务器上总共有多少显卡后&#xff0…

第一章:Go语言简介

Go语言&#xff08;或 Golang&#xff09;起源于 2007 年&#xff0c;并在 2009 年正式对外发布。Go 是非常年轻的一门语言&#xff0c;它的主要目标是“兼具 Python 等动态语言的开发速度和 C/C 等编译型语言的性能与安全性”。 Go语言是编程语言设计的又一次尝试&#xff0c…

41-剑指 Offer 43. 1~n 整数中 1 出现的次数

题目 输入一个整数 n &#xff0c;求1&#xff5e;n这n个整数的十进制表示中1出现的次数。 例如&#xff0c;输入12&#xff0c;1&#xff5e;12这些整数中包含1 的数字有1、10、11和12&#xff0c;1一共出现了5次。 示例 1&#xff1a; 输入&#xff1a;n 12 输出&#x…

【Activiti工作流引擎】基本认识Activiti

Activiti工作流引擎 表的命名结构 ACT_RE &#xff1a;RE’表示 repository。这个前缀的表包含了流程定义和流程静态资源 &#xff08;图片&#xff0c;规则&#xff0c;等等&#xff09;。 ACT_RU&#xff1a;RU’表示 runtime。这些运行时的表&#xff0c;包含流程实例&am…

海外拥有最庞大社区人群的Verasity($VRA),后市值得期待

在2023年开年以来&#xff0c;随着主流标的回暖进一步带动大盘的上涨&#xff0c;并且加密货币总市值重回1亿美元以上。而加密货币市场大多数资产都迎来普涨。我们看到&#xff0c;短时的上涨虽然为市场重新注入信心&#xff0c;但能够持续具备上涨趋势的标的并不多。此前&…

layui框架实战案例(18):保存草稿和单选radio复选框checkbox无focus属性快速聚焦跳转的解决方案

系列文章目录 layui动态表格翻页和搜索的代码分析layui框架实战案例(3)&#xff1a;layui上传错误请求上传接口出现异常解决方案layui框架实战案例(9)&#xff1a;layPage 静态数据分页组件layui框架实战案例(10)&#xff1a;短信验证码60秒倒计时layui框架实战案例(11)&#…

SSE(Server-sent Events)实现Web消息推送(SpringBoot)

本文参考自&#xff1a; Web消息推送之SSE_魅Lemon的博客-CSDN博客_sse推送 【IT老齐237】超好用Web服务端主动推送技术SSE_哔哩哔哩_bilibili 1、Web消息推送简介 短轮询 长轮询 iframe流 SSE MQTT websocket 2、SSE原理介绍 2.1、概念 SSE(Server Sent Event)&…

43.Isaac教程--图像变形

图像变形 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 文章目录图像变形几何畸变图像投影透视畸变校正径向畸变校正切向畸变校正其他相机固有参数焦距主点&#xff08;投影中心&#xff09;未失真输出的光学特性输出主点输出焦距输出图像大小输…

最快的树视图组件:Flexible TreeView.NET Crack

为什么要使用灵活的 TreeView&#xff1f; 灵活性 市场上其他类似树视图的组件所不具备的无与伦比的可扩展性和独特功能。 表现 市场上最快的树视图组件。 仅需 0.39 秒即可添加 100,000 个节点。 简单 尽管是一个非常强大的树视图组件&#xff0c;但 Flexible TreeView 被设计…

Java开发基于rmi的数据库中间件设计源码,并利用中间件建立一个数据库应用(Java web项目),分布式对象技术课程实践

基于rmi的数据库中间件设计 介绍 分布式对象技术课程实践&#xff1a;基于rmi的数据库中间件设计&#xff0c;并利用中间件建立一个数据库应用&#xff08;Java web项目&#xff09;。 软件架构 前端&#xff1a;React后端&#xff1a;Springboot数据库中间件&#xff1a;J…

【人脸检测】------MTCNN算法

MTCNN算法出自深圳先进技术研究院,乔宇老师组,是今年2016的ECCV。 正如上图所示,该MTCNN由3个网络结构组成(P-Net,R-Net,O-Net)。 Proposal Network (P-Net):该网络结构主要获得了人脸区域的候选窗口和边界框的回归向量。并用该边界框做回归,对候选窗口进行校准,然后通…

Ubuntu18.04下QT和MYSQL异常问题排查处理常用命令

问题场景 &#xff1a;开年第一天上班&#xff0c;使用GIT下载好项目代码到本地后&#xff0c;发现QT5.14.2无法正常启动&#xff0c;使用命令sudo /opt/Qt5.14.2/Tools/QtCreator/bin/qtcreator后没有任何反应&#xff0c;仔细回想应该是年前电脑修改环境变量导致无法进入系统…

微信小程序安全系列——文本内容安全识别

前言 相信很多朋友跟我遇到过相同的问题&#xff0c;就是在开发一些笔记或者博客的时候&#xff0c;会遇到一些过滤敏感、时政、黄、赌、毒这类词汇、句子等这种棘手问题。 今天我们看一下微信小程序提供的文本安全内容识别&#xff0c;也可以减少一些我们的工作量。通过微信…

【通信原理(含matlab程序)】实验二:FM的调制和解调

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; 本人持续分享更多关于电子通信专业内容以及嵌入式和单片机的知识&#xff0c;如果大家喜欢&#xff0c;别忘点个赞加个关注哦&#xff0c;让我们一起共同进步~ &#x…

bug解决:Uncaught (in promise) TypeError: Toast.loading is not a function

在使用vue3做项目时&#xff0c;在其中使用了vant框架&#xff0c;在使用toast的加载组件或者是一些其他组件时&#xff0c;出现了如下的错误&#xff1a;Uncaught (in promise) TypeError: Toast.loading is not a function错误代码如下&#xff1a;Toast.loading({ message: …

二本土木工程毕业四年,成功转行大数据

1、 自我介绍 大家好&#xff0c;我是临渊羡鱼。18年毕业与重庆的一所二本大学&#xff0c;至今4年有余&#xff0c;专业是土木工程&#xff0c;毕业后从事三年半的建筑结构设计工作&#xff0c;在此期间由于不看好设计行业前景&#xff0c;故而在21年底谋求转行。在朋友推荐下…

[C语言]文件操作

目录 1.文件 1.1程序文件 1.2数据文件 2.文件名 3.文件的打开和关闭 3.1文件指针 3.2文件的打开和关闭 4.文件的顺序读写 4.1fgetc 4.2fputc 4.3fgets 4.4fputs 4.5fscanf 4.6fprintf 4.7fread&#xff08;二进制输出&#xff09; 4.8fwriite&#xff08;二进制输…

Python【xpath】实战案例【中】

获取全国地级城市名称&#xff1a;案例准备&#xff1a;导入外部库 1.requests、2.lxml容易遇到的问题&#xff1a;网站SSL认证失效代码块&#xff1a;#导入第三方库 import requests from lxml import etree # 网页地址 url https://www.aqistudy.cn/historydata/ #U-A伪装 h…

SOFA Weekly|SOFANews、issue 精选

SOFA WEEKLY | 每周精选 筛选每周精华问答&#xff0c;同步开源进展欢迎留言互动&#xff5e;SOFAStack&#xff08;Scalable Open Financial Architecture Stack&#xff09;是蚂蚁集团自主研发的金融级云原生架构&#xff0c;包含了构建金融级云原生架构所需的各个组件&#…

论文投稿指南——中文核心期刊推荐(公路运输)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…