C++对C的扩充(三)

5 带缺省参数的函数

一般情况下,实参个数应与形参个数相同。C++允许实参个数与形参个数不同。办法是在形参表列中对一个或几个形参指定缺省值(或称默认值)。例如某一函数的首部可用如下形式:

void fun(int a, int b,int c=100)

在调用此函数时如写成fun(2,4,6),则形参a,b,c的值分别为2,4,6(这是与过去一样的)。如果写成fun(2,4),即少写了最后一个参数,由于在函数定义时已指定了c的缺省值为100,因此a,b,c的值分别为2,4,100。请注意:赋予缺省值的参数必须放在形参表列中的最右端。例如:

void f1(float a, int b, int c=0, char d='a') (正确)

void f2(float a, int c=0, char d='a', int b) (不正确)

利用这一特性,可以使函数的使用更加灵活。例如例14.4求两个数或3个数中的最大数。也可以不用重载函数,而将函数max的首行写成

int max(int a, int b,int c=-32768)

如果只想从两个数中找大者,则可以在调用时写成max(100,675),c的值自动取 -32768,由于一32768是最小整数,因此从100,675,-32768中选大者和从100,675中选大者的结果是一样的。

注意:不要同时使用重载函数和缺省参数的函数,因为当调用函数时少写一个参数,系统无法判定是利用重载函数还是利用缺省参数的函数,会发生错误。

6变量的引用类型

6.1 引用的概念

“引用”(reference)是C++的一种新的变量类型,是对C的一个重要扩充。它的作用是为一个变量起一个别名。假如有一个变量a,想给它起一个别名b,可以这样写:

int a;

int&b=a:

这就声明了b是a的“引用”,即a的别名。经过这样的声明后,使用a或b的作用相同,都代表同一变量。注意:在上述声明中,&是“引用声明符”,并不代表地址。不要理解为“把 a的值赋给b的地址”。声明引用并不另开辟内存单元,b和a都代表同一变量单元。在声明一个引用型变量时,必须同时使之初始化,即声明它代表哪一个变量,在声明一个变量的引用后,在本函数执行期间,该引用一直与其代表的变量相联系,不能再作为其他变量的别名。下面的用法不对:

int al,a2;

int&b=a1;

int&b=a2; (企图使b变成a2的引用(别名)是不行的)

6.2 引用的简单使用

通过下面的例子可以了解引用的简单使用。

例14.5 了解引用和变量的关系。

# include <iostream.h>

# include <iomanip.h>

void main( )

{inta=10;

int &b=a; //声明b是a的引用

a=a*a; //a的值变化了,b的值也应一起变化

cout<<a<<setw(6)<<b;

b=b/5; //b的值变化了,a的值也应一起变化

cout<<b<<setw(6)<<a;

}

a 的值开始为10,b是a的引用,它的值当然也应该是10,当a的值变为100(a*a的值)时,b

的值也随之变为100。在输出a和b的值后,b的值变为20,显然a的值也应为20(见图14.1)。运行记录如下:

100 100

  1. 20

6.3 引用作为函数参数

有了变量名,为什么还需要一个别名呢?C++之所以增加“引用”,主要是把它作为函数参数,以扩充函数传递数据的功能。

在C语言中,函数的参数传递有以下两种情况。

(1)将变量名作为实参。这时传给形参的是变量的值。传递是单向的,在执行函数期间形参值发生变化并不传回给实参,因为在调用函数时,形参和实参不是同一个存储单元。下面的程序无法实现两个变量的值互换。

例14.6错误的程序。

# include <iostream.h>

void swap(int a, int b)

{int temp;

temp=a;

a=b;

b=temp; //实现a和b的值互换

}

void main( )

{int i=3,j=5;

swap(i,j);

cout<<i<<","<<j<<endl; //i和j的值未互换

}

输出i和j的值仍为3和5。见图14.2示意。图14.2(a)表示调用函数时的数据传递,图14.2(b) 是执行swap函数体后的情况,a和b值的改变不会改变i和j的值。

为了解决这个问题,在第10章介绍了传递变量地址的方法。

  1. 传递变量的指针。使形参得到一个变量的地址,这时形参指针变量指向实参变量单元。程序见例14.7。

例14.7 使用指针变量作形参,实现两个变量的互换。

# include <iostream.h>

void swap(int* p1,int *p2)

{int temp;

temp=*pl;

*p1=*p2;

p2=temp;

}

void main( )

{int i=3,j=5;

swap(&i.&j);

cout<<i<<"."<<j<<endl;

}

形参与实参的结合见图14.3示意。调用函数时把变量;和j的地址传送给形参p1和 p2(它们是指针变量),因此*p1和i为同一内存单元,*p2和j为同一内存单元,图14.3(a)表示刚调用swap函数时的情况,图14.3(b)表示执行完函数体语句时的情况,显然,i和j的值改变了。

这种方法其实也是采用“值传递”方式,向一个指针变量传送一个地址。然后再通过指针变量访问有关变量。这样做能得到正确结果,但是在概念上“兜了一个圈子”,不那么直截了当。在PASCAL语言中有“值形参”和“变量形参”(即var形参),对应两种不同的传递方式,前者采用值传递方式,后者采用地址传递方式(传送的是变量的地址而不是变量的值,使形参指向一个变量)。在C语言中,只有“值形参”而无“变量形参”,全部采用值传递方式。C+十把引用型变量作为函数形参,就弥补了这个不足。

C++提供了向函数传递数据的第三种方法,即传送变量的别名。

例14.8 利用“引用形参”实现两个变量的值互换。

#include <iostream.h>

void swap (int &a,int &b)

{int temp;

temp=a;

a=b;

b=temp;

}

void main( )

{inti=3,j=5;

swap(i,j);

cout<<"i="<<i<<""<<j<<" <<endl;

}

输出结果为 i=5 j=3

        在swap函数的形参表列中声明变量a和b是整型的引用变量(和其他变量一样,既可以在函数体中声明变量的类型,也可以在定义函数时在形参表列中声明变量的类型)。请注意:在此处&a 不是“a 的地址”,而是指“a是一个引用型变量”。但是此时并未对它们初始化,即未指定它们是哪个变量的别名。当 main 函数调用swap函数时由实参把变 量名传给形参。i的名字传给引用变量a,这样a就成了i的别名。同理,b成为j的别名。a和i代表同一个变量,b和j代表同一个变量。在swap函数中使a和b的值对换,显然,i和j的值同时改变了(见图14.4示意,其中(a)是刚开始执行swap函数时的情况,(b)是执行完函数体语句时的情况)。在main函数中输出i和j已改变了的值。

        实际上,实参传给形参的是变量的地址,也就是使形参a具有变量i的地址,从而使a和i共享同一单元。为便于理解,我们说把变量i的名字传给引用变量a,使a成为i的别名。请注意这种传递方式和使用指针变量作形参时有什么不同?分析例14.8(对比例14.7),可以发现:①不必在swap函数中设立指针变量,指针变量要另外开辟内存单元、其内容是地址。而引用变量不是一个独立的变量,不单独占内存单元,在本例中其值为一整数。②在main函数中调用swap函数时实参不必在变量名前加&.以表示地址。这种传递方式相当于PASCAL语言中的“变量形参”,系统传送的是实参的地址而不是实参的值。显然,这种用法比使用指针变量简单、直观、方便。

的前面有类型符时(如int&a),它必然是对引用的声明;如果前面无类型符(如&a),则是取变量的地址。

7内置函数

        调用函数时需要一定的时间,如果有的函数需要频繁使用,则所用时间会很长,从而降低程序的执行效率。C++提供一种提高效率的方法,即在编译时将所调用函数的代码嵌人到主调函数中。这种嵌入到主调函数中的函数称为内置函数(inline function),又称内嵌函数。在有些书中把它译成“内联函数”。

        指定内置函数的方法很简单,只需在函数首行的左端加一个关键字inline即可。

例 14.9 将函数指定为内置函数。

# include <iostream.h>

inline int max(int a,int b,int c) //这是一个内置函数,求3个整数中的最大者

{ if(b>a)a=b;

 if(c>a)a=c;

 return a;

}

void main( )

{int i=7,j=10,k=25,m;

m=max(i,j,k):

cout<<" max="<<m<<endl;

}

由于在定义函数时指定它为内置函数,因此编译系统在遇到函数调用max(i,j,k)时,就用max函数体的代码代替max(i,j,k),同时将实参代替形参。这样,m=max(i,j, k)就被置换成

if(>i)i=j;

if(k>i)i=k;

m=it

内置函数与宏替换有些相似,但不完全相同。宏替换是在编译前由预处理程序进行预处理.它只作简单的字符替换而不作语法检查。而内置函数是在编译时处理的,编译程序能识别内置函数,对它进行语法检查。有些问题既可以用宏来处理,也可以用内置函数处理,显然,内置函数优于宏替换,它不会出现宏替换中可能产生的副作用。

使用内置函数可以节省运行时间,但却增加了目标程序的长度。假设要调用10次 max函数,则在编译时先后10次将max的代码复制并插人main函数,大大增加了main函数的长度。因此只用于规模很小而使用频繁的函数,可大大提高运行速度。

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

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

相关文章

kubernetes(K8S)学习(五):K8S进阶(Lifecycle......偏理论)

K8S进阶&#xff08;Lifecycle......偏理论&#xff09; 一、Pod进阶学习之路1.1 Lifecycle1.2 重启策略1.3 静态Pod1.4 健康检查1.5 ConfigMap1.6 Secret1.7 指定Pod所运行的Node 二、Controller进阶学习之路2.1 Job & CronJob2.2 StatefulSet2.3 DaemonSet2.4 Horizontal…

Adobe Illustrator 2023 for Mac/Win:创意无限,设计无界

在数字艺术与设计领域&#xff0c;Adobe Illustrator 2023无疑是一颗璀璨的明星。这款专为Mac和Windows用户打造的矢量图形设计软件&#xff0c;以其强大的功能和卓越的性能&#xff0c;赢得了全球设计师的广泛赞誉。 Adobe Illustrator 2023在继承前代版本优点的基础上&#…

鸿蒙 UIAbility和Compent 生命周期

一、UIAbility的生命周期 在UIAbility的使用过程中&#xff0c;会有多种生命周期状态&#xff0c;掌握UIAbility的生命周期&#xff0c;对于应用的开发非常重要。 1、UIAbility的生命周期 UIAbility的生命周期主要分为以下4个&#xff1a; Create---Foreground---Background---…

多模态大模型:解析未来智能汽车的新引擎

多模态大模型&#xff1a;解析未来智能汽车的新引擎 1. 多模态大模型简介2. 多模态大模型在智能汽车中的应用2.1 感知与认知2.2 智能驾驶辅助2.3 智能交互 随着人工智能技术的不断进步&#xff0c;智能汽车已经从概念变成了现实&#xff0c;成为了当今科技领域的焦点之一。而在…

大模型预测,下一个token何必是文字?

太快了太快了… 大模型的生成技能&#xff0c;已经到了普通人看不懂的境界&#xff01; 它可以根据用户过去5年的体检报告&#xff0c;生成未来第1年、第2年、第3年的体检报告。 你看&#xff0c;这个生成的过程&#xff0c;是不是像极了ChatGPT&#xff0c;根据历史单词预测…

顺序栈、链式栈、顺序队列、链式队列的ADT及其实现

顺序栈ADT及其实现 链式栈ADT及其实现 顺序队列的ADT及其实现 在数组中队首队尾的分配方案 第三中方案&#xff0c;即达到入队出队操作的时间代价是O&#xff08;1&#xff09; 同时可充分利用空间&#xff0c;不会出现空间似乎用完了的假象 时间性能和空间性能发挥到最大 链…

快速上手Spring Cloud 九:服务间通信与消息队列

快速上手Spring Cloud 一&#xff1a;Spring Cloud 简介 快速上手Spring Cloud 二&#xff1a;核心组件解析 快速上手Spring Cloud 三&#xff1a;API网关深入探索与实战应用 快速上手Spring Cloud 四&#xff1a;微服务治理与安全 快速上手Spring Cloud 五&#xff1a;Spring …

短视频矩阵系统---开发源头交付

短视频矩阵系统---开发源头交付 短视频矩阵系统的核心开发步骤包括以下几个方面&#xff1a; 1. 系统设计&#xff1a;根据需求分析&#xff0c;设计出相应的系统架构&#xff0c;包括数据库设计、系统功能模块设计等。 2. 开发基础功能&#xff1a;基础功能包括短视频的上传、…

数据库工具——DBeaver的安装及使用

目录 一、DBeaver介绍 1.定义 2.支持的数据库 3.支持的操作系统 4.特点 二、DBeaver安装及使用 1.服务启动 2.查看连接类型 3.演示连接Mysql数据库 4.连接配置 5.成功连接 6.远程控制 6.1新建数据库 6.2新建数据表 6.3添加字段列 6.4使用SQL编辑器进行编辑 一…

双向长短期BiLSTM的回归预测-附MATLAB代码

BiLSTM是一种带有正反向连接的长短期记忆网络&#xff08;LSTM&#xff09;。 BiLSTM通过两个独立的LSTM层&#xff0c;一个按时间顺序处理输入&#xff0c;另一个按时间倒序处理输入&#xff0c;分别从正向和反向两个方向捕捉输入序列的特征。具体地&#xff0c;正向LSTM按时…

蓝桥杯物联网竞赛_STM32L071_13_定时器

CubeMx配置LPTIM: counts internal clock events 计数内部时钟事件 prescaler 预分频器 updata end of period 更新期末 kil5配置&#xff1a; 中断回调函数完善一下&#xff1a; void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim){if(cnt ! 10) cnt…

Python:执行py命令,提示: Can‘t find a default Python.

1.Python运行环境罢工 今天&#xff0c;要运行一个前年用python编写的爬虫程序&#xff0c;先检测python运行环境是否正常&#xff1a; D:\Python38-32\works>c:\windows\py.exe Cant find a default Python. 再试&#xff1a; D:\Python38-32\works>py --list Installe…

基于单片机的便携式瓦斯检测仪系统设计

**单片机设计介绍&#xff0c;基于单片机的便携式瓦斯检测仪系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的便携式瓦斯检测仪系统设计是一个针对煤矿等工业环境中瓦斯气体浓度检测的重要项目。以下是该设计…

RN在android/ios手机剪切图片的操作

之前写过一个React Native调用摄像头画面及拍照和保存图片到相册全流程但是这个仅限于调用摄像头拍照并保存图片,今天再写一个版本的操作,这个博客目前实现的有三点操作: 调用摄像头拍照对照片进行剪切从相册选取图片 功能上面来说有两点: 点击按钮可以对摄像头进行拍照,拍完照…

C++进阶,手把手带你学继承

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;c大冒险 总有光环在陨落&#xff0c;总有新星在闪烁 【本节目标】 1.继…

引领2024年的人工智能前景:趋势、预测和可能性(万字长文)

欢迎来到2024年人工智能和技术的可能性之旅。在这里&#xff0c;每一个预测都是一个潜在的窗口&#xff0c;未来充满了创新、变化&#xff0c;更重要的是&#xff0c;机会类似于20世纪50年代的工业革命。50年代见证了数字计算的兴起&#xff0c;重塑了行业和社会规范。今天&…

【面经】2023年软件测试面试题大全(持续更新)附答案

前阵子一位读者告诉我&#xff0c;某位大厂HR给他发了我之前做的面试题答案合集。 这个消息让我开心了一整天&#x1f602;&#xff0c;因为这说明我之前做的面试题系列真的能帮助到部分测试同学&#xff0c;也算是侧面得到了一种认可吧。 坚持可是我们程序员家族的优良传统&a…

实时语音识别(Python+HTML实战)

项目下载地址&#xff1a;FunASR 1 安装库文件 项目提示所需要下载的库文件&#xff1a;pip install -U funasr 和 pip install modelscope 运行过程中&#xff0c;我发现还需要下载以下库文件才能正常运行&#xff1a; 下载&#xff1a;pip install websockets&#xff0c;pi…

【爬虫开发】爬虫从0到1全知识md笔记第2篇:requests模块,知识点:【附代码文档】

爬虫开发从0到1全知识教程完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;爬虫课程概要&#xff0c;爬虫基础爬虫概述,,http协议复习。requests模块&#xff0c;requests模块1. requests模块介绍,2. response响应对象,3. requests模块发送请求,4. request…

【C++的奇迹之旅】C++关键字命名空间使用的三种方式C++输入输出命名空间std的使用惯例

文章目录 &#x1f4dd;前言&#x1f320; C关键字(C98)&#x1f309; 命名空间&#x1f320;命名空间定义&#x1f309;命名空间使用 &#x1f320;命名空间的使用有三种方式&#xff1a;&#x1f309;加命名空间名称及作用域限定符&#x1f320;使用using将命名空间中某个成员…