C++入门学习(2)

思维导图:

一,缺省参数

如何理解缺省参数呢?简单来说,缺省参数就是一个会找备胎的参数!为什么这样子说呢?来看一个缺省参数就知道了!代码如下:

#include<iostream>
using  std::cout;
using std::endl;
int Add(int a = 70, int b = 5)
{
	return a + b;
}

int main()
{
	int ret1 = Add();
	int ret2 = Add(100, 80);

	cout <<"ret1:" << ret1 << endl;
	cout <<"ret2:" << ret2 << endl;
}

这个程序打印的结果是什么呢?通过程序运行可以看到打印的结果是:

ret1:75
ret2:180

通过这个程序的运行你大概知道缺省参数是个什么东西了吧!再来一个代码:

#include<iostream>
using  std::cout;
using std::endl;
void Print(int a = 5, int b = 6, int c = 7)
{
	cout << a << " ";
	cout << b << " ";
	cout << c << endl;
}
int main()
{
	Print();
	Print(9);
	Print(8, 8);
	Print(6, 6, 6);
	return 0;
}

 这段代码打印的结果是什么呢?程序运行打印结果如下:

5 6 7
9 6 7
8 8 7
6 6 6

可以看到当我们在调用Print这个函数时如果在外面传入值的话,在Print函数运行时就会使用外面传入的值。如果外面没有传入值的话就会使用函数参数被赋予的值。这个被赋予的值就是缺省值!所以对应的参数就被叫做缺省参数缺省参数分为全缺省和半缺省!半缺省不是缺省一半而是缺省部分参数。

使用缺省参数时要注意的点

 1.在外面传入数值时要从左往右传。假如跳着传就会报错。

  如对第二个函数Print,如果这样传参就会报错:

Print(,9,);//跳过第一个传参直接传给第二个参数

 2.缺省参数要从右往左缺省。

  如对第二个函数Print的缺省值调整成下面的样子就会报错:

void Print(int a = , int b = 6, int c = 7)

 3.声明和定义中不能都给缺省值,要给最好在声明中给。

缺省参数的作用

上面说了一大堆关于缺省参数的东西,那这个缺省参数究竟有什么作用呢?下面我们来回顾一个叫做顺序表的东西。为了将顺序表的空间开辟出来,我们大概需要经历三步: 

typedef  struct List
{
	int *a;
	int size;
	int capacity;
}List;

void ListInit(List* pList)
{
	pList->a = NULL;
	pList->size = 0;
	pList->capacity = 0;
}
void PushBack(List* pList)
{
	//检查是否为NULL,malloc空间
	// 检查是否需要扩容,realloc
	//……
}
int main()
{
	List s;
	ListInit(&s);
	PushBack(&s);
	return 0;
}

 但是有了缺省参数我们便可以一步搞定了,一开始想开多大就开多大。代码如下:

typedef  struct List
{
	int* a;
	int size;
	int capacity;
}List;

void ListInit(List* pList, int n = 4)
{
	int* a = (int*)malloc(sizeof(int) * n);
	pList->size = 0;
	pList->capacity = n;
}
int main()
{
	List s;
	ListInit(&s);//不像开辟就默认开辟四个(缺省值个)空间
	List p;
	ListInit(&p, 100);//像开辟一百个空间就开辟一百个空间
	return 0;
}

 虽然在C语言中可以用宏定义来解决,但是宏定义不够灵活。当我们每次开辟不同的空间大小时每次都要改宏,当我们要搞两个顺序表时就要定义两个宏,三个顺序表就要三个宏,非常麻烦!!!

 二,函数重载

函数重载这个概念就是祖师爷对于C语言语法的补充了。什么叫做函数重载呢?构成函数重载的条件是什么呢?下面我们就来探讨一下。

函数重载的条件

1.函数名相同

2.函数的参数类型不同or参数个数不同or参数的类型顺序不同。

 比如下面的代码:

int Add(int x, double y)
{
	return x + y;
}
//类型不同
int Add(int x, int y)
{
	return x + y;
}
//个数不同
int Add(int x, double y, int z)
{
	return x + y + z;
}
//顺序不同
int Add(double x, int y)
{
	return x + y;
}

 这些情况便构成函数重载。在判断函数重载时有一个情况是非常容易迷惑人的就是返回值不同是不会构成函数重载的!例如下列情况。

 代码:

int Add(int x, double y)
{
	return x + y;
}

double Add(int x, double y)
{
	return x + y;
}

char Add(int x, double y)
{
	return x + y;
}
//……还有很多只是返回值的类型不同的情况都不构成函数重载!

函数重载的作用

有了函数重载,那我们便可以少取名了。要使用相同功能但是数据类型or个数不同的函数时改一下参数的类型or个数or顺序就可以了!!!

三,引用

 cpp中的引用可谓是一大进步。有了引用以后指针的很多功能都能被引用代替,极大的提高了cpp程序的使用感受。既然引用如此可爱那我们一定要去认识一下它。

1.引用的格式

到底在cpp中如何写才能被称为是引用呢?

现在来看看引用的格式特点:类型+&+变量名。当你看到这样的语句时便可以知道这个变量就是一个引用。如:

int a = 1;
int& b = a;//b就是对a的一个引用。

2.引用的本质

 如果用xxx引用一个变量,有一个通俗的说法叫做给这个变量取了一个”xxx“的别名。

就比如周树人的笔名叫作鲁迅,那提到鲁迅是不是就是提到周树人呢?周树人的家门前有两棵树那鲁迅家门前有没有两棵树呢?这两个的答案当然就是肯定的,因为一个人的名字可以有很多但是人只有一个。cpp中的引用的意思就和这两个例子的意思差不多!!!现在来验证一下:

   int main()
{
	int a = 1;
	int& b = a;//b就是对a的一个引用。

	//取两者的地址验证这两个变量是否指向同一个地址
	cout << "address of a:" << &a << endl;
	cout << "address of b:" << &b << endl;

	return 0;
}

结果:

address of a:001EFB84
address of b:001EFB84

通过验证可以看到引用ba是指向同一块空间的两个不同的名字。

3.引用的特点

1.引用必须初始化

int main()
{
	int a = 1;
	int& b ;//未对引用b初始化
	return 0;
}

上面的代码就会报错。报错:

2.引用只能引用一个实体,就像人可以有很多名字但是人只有一个一样。

//引用多个实体
int main()
{
	int a = 1;
	int& b = a;

	int c = 0;
	int& b = c;
	return 0;
}

这样也会报错。报错:

但是这样是可以的,因为这是赋值:

//赋值
int main()
{
	int a = 1;
	int& b = a;

	int c = 0;
    b = c;
	return 0;
}

 3.一个实体可以有多个别名就像一个人可以有多个名字一样。

//一个实体可以有多个别名
int main()
{
	int a = 0;
	int& b = a;
	int& c = a;
	int& d = a;
	//……
	return 0;
}

4. 引用不能引用空指针

//不能引用空指针
int main()
{
	int& a = nullptr;
	return 0;
}

报错:

//不能引用空指针
int main()
{
	int& a = NULL;
	return 0;
}

报错:

四,使用引用的两种形式

 1.引用作参数(输出型参数)

当函数中的一个参数的作用是用来做输出型参数时便可以考虑使用引用做参数。

补充:

1.输出型参数:输出型参数的作用就是为了改变外面传入参数的数据。

2.输入性型参数:输入型参数就是给函数内部传入数据。

这里经典的要传输入型参数的函数就是swap函数

void swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

这个swap函数使用的是指针来交换a,b两个变量的数据。

//引用
void swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}
int main()
{
	int a = 0;
	int b = 10;
	cout << "swap前a:" << a << endl;
	cout << "swap前b: " << b << endl;
	swap(a, b);//swap函数调用
	cout << endl;
	cout << "swap后a:" << a << endl;
	cout << "swap后b: " << b << endl;
	return 0;
}

结果:

swap前a:0
swap前b: 10

swap后a:10
swap后b: 0

二,引用做返回值

 用引用做返回值是一个得十分谨慎的事情。因为引用卓返回值是有前提的,前提就是出了返回值函数的作用域以后返回值的实体不能被销毁。

1.其它类型的函数返回是怎么做的呢?

图解:

 通过上面的过程n的数据便被返回到ret中接收。

2.引用作返回值

引用做返回值就和一般类型的返回不同了。因为传引用返回是不产生临时变量的。

但是在n出了函数add以后,n就被销毁了。这个时候就要看运气了。当n里面的值还没有被清理时便可以让ret接收,当n中的被清理以后ret接收的值就是随机值了。所以当返回值在被接收前是会被销毁的参数时就要谨慎使用了。

应该传引用返回的场景

 当变量是静态变量,堆上的变量,全局变量时便可以大胆的使用传引用返回。因为这些变量是不会被系统轻易销毁的。又因为使用传引用变量可以减少数据的拷贝,所以传引用返回的效率会更高。所以在可以使用传引用返回的场景应该多多使用传引用返回。

补充:利用传引用返回来修改顺序表里面的值和读取第i个位置的值。

C语言版本:

//C语言读取第i个位置的值
int Find(List* ps, int i)
{
	assert(ps);
	return ps->a[i];
}
//修改第i个位置的值
void SLModify(List* ps, int i, int x)
{
	assert(i < ps->size);
	ps->a[i] = x;
}

C++利用引用版本:


int& SLAC(List& ps,int i)
{
	assert(i < ps.size);
	return ps.a[i];
}

 从这里便可以看出cpp的引用有多香了!哈哈!

补充:

使用引用时不能发生权限的扩大。可以发生权限的平移和缩小。

如:

int main()
{
	double a = 1;
	int b = a;
}

这个程序是可以运行的,但是换成下面的代码便会报错:

int main()
{
	double a = 1;
	int& b = a;
}

这是为什么呢?这是因为,在第一个程序中双精度浮点型的a要传给整型的b就会发生如下图所示的过程:

 在双精度浮点型的a传给b时会发生隐式转换,这个过程会产生一个临时变量。临时变量有一个特点就是具有常性。所以在将a的值再赋值给b时就会发生权限的扩大!那该如何搞定这个错误呢?解决方法如下:

int main()
{
	double a = 1;
	const int& b = a;//在b前面加一个const修饰符
}

这样b便也有了常性,这样就相当于权限的平移了!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法与数据结构-排序

文章目录 一、如何分析一个排序算法1.1 排序算法的执行效率1.1.1 最好情况、最坏情况、平均情况时间复杂度1.1.1.1 最好、最坏情况分析1.1.1.2 平均情况分析 1.1.2 时间复杂度的系数、常数 、低阶1.1.3 比较次数和交换&#xff08;或移动&#xff09;次数 1.2 排序算法的内存消…

Go语言之重要数组类型map(映射)类型

通过切片&#xff0c;我们可以动态灵活存储管理学生姓名、年龄等信息&#xff0c;比如 names : []string{"张三","李四","王五"} ages : []int{23,24,25} fmt.Println(names) fmt.Println(ages)但是如果我想获取张三的年龄&#xff0c;这是一个…

C# 同构字符串

205 同构字符串 给定两个字符串 s 和 t &#xff0c;判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t &#xff0c;那么这两个字符串是同构的。 每个出现的字符都应当映射到另一个字符&#xff0c;同时不改变字符的顺序。不同字符不能映射到同一个字符…

详细介绍MATLAB中的图论算法

MATLAB是一种功能强大的编程语言和环境,提供了许多用于图论算法的工具和函数。图论是研究图及其属性和关系的数学分支,广泛应用于计算机科学、网络分析、社交网络分析等领域。在MATLAB中,我们可以使用图论算法来解决各种问题,如最短路径问题、最小生成树问题、最大流问题等…

国产MCU-CW32F030开发学习-BH1750模块

国产MCU-CW32F030开发学习-BH1750模块 硬件平台 CW32_48F大学计划板CW32_IOT_EVA物联网开发评估套件BH1750数字型光照强度传感器 BH1750 BH1750是一款数字型光照强度传感器&#xff0c;能够获取周围环境的光照强度。其测量范围在0~65535 lx。lx勒克斯&#xff0c;是光照强…

【电路效应】信号处理和通信系统模型中的模拟电路效应研究(SimulinkMatlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码、Simulink仿真实现 &#x1f4a5;1 概述 在信号处理和通信系统模型中&#xff0c;模拟电路效应研究是指考虑到实际电路的特性对信号进行建模和分析的过程。模拟电路效应…

Kubernetes—集群故障排查

一、用 Kubectl 调试 Kubernetes 节点 准备开始 你必须拥有一个 Kubernetes 的集群&#xff0c;同时你必须配置 kubectl 命令行工具与你的集群通信。 建议在至少有两个不作为控制平面主机的节点的集群上运行本教程。 你的 Kubernetes 服务器版本必须不低于版本 1.2. 要获知版…

C#基础--委托

C#基础–委托 C#基础–委托 简单说它就是一个能把方法当参数传递的对象&#xff0c;而且还知道怎么调用这个方法&#xff0c;同时也是粒度更小的“接口”&#xff08;约束了指向方法的签名&#xff09; 一、什么是委托&#xff0c;委托的本质是什么&#xff1f; 跟方法有点类似…

云迁移第二波热潮来袭,你准备好了吗?

最近&#xff0c;云迁移再次被频繁提及&#xff0c;企业对云迁移的需求量有回升趋势&#xff0c;究其根本&#xff0c;主要有以下原因&#xff1a; 企业数字化进程加速&#xff0c;本地上云需求强劲 根据《2021中国企业上云指数洞察报告》&#xff0c;我国实体经济上云渗透率…

深入理解Java虚拟机(二)Java内存区域与内存溢出异常

一、前言 对于Java程序员来说&#xff0c;在虚拟机自动内存管理机制的帮助下&#xff0c;不再需要为每一个new操作去写配对的delete/free代码&#xff0c;不容易出现内存泄漏和内存溢出问题&#xff0c;看起来由虚拟机管理内存一切都很美好。不过&#xff0c;也正是因为Java程序…

kafka接收外部接口的数据,并实现转发

目录 一、什么是kafka 二、kafka接收外部接口数据 三、kafka收到数据后转发 四、kafka总结 一、什么是kafka Kafka是一种分布式流式处理平台&#xff0c;最初由LinkedIn开发。它设计用于高吞吐量、低延迟的数据处理&#xff0c;能够处理大规模的实时数据流。Kafka采用发布…

关系型数据库设计规则

目录 1.1 表、记录、字段 1.2 表的关联关系 1.2.1 一对一关联&#xff08;one-to-one&#xff09; 1.2.2 一对多关系&#xff08;one-to-many&#xff09; 1.2.3 多对多&#xff08;many-to-many&#xff09; 1.2.4 自我引用&#xff08;Self reference&#xff09; 关系…

用Python采用Modbus-Tcp的方式读取485电子水尺数据

README.TXT 2023/6/15 V1.0 实现了单个点位数据通信、数据解析、数据存储 2023/6/17 V2.0 实现了多个点位数据通信、数据解析、数据存储 2023/6/19 V2.1 完善log存储&#xff0c;仅保留近3天的log记录&#xff0c;避免不必要的存储&#xff1b;限制log大小&#xff0c;2MB。架…

基于Redisson的Redis结合布隆过滤器使用

一、场景 缓存穿透问题 一般情况下&#xff0c;先查询Redis缓存&#xff0c;如果Redis中没有&#xff0c;再查询MySQL。当某一时刻访问redis的大量key都在redis中不存在时&#xff0c;所有查询都要访问数据库&#xff0c;造成数据库压力顿时上升&#xff0c;这就是缓存穿透。…

成为一个年薪30W+的DFT工程师是一种什么体验?

一直以来&#xff0c;DFT都是数字IC设计行业中相对神秘的一个岗位。 你说他重要吧&#xff0c;并不是所有芯片设计公司都有这个岗位&#xff0c;你说他不重要吧&#xff0c;但凡芯片产品达到一定规模后&#xff0c;就必须设置DFT部门。 一、什么是DFT&#xff1f; DFT&#x…

【分布式应用】ceph分布式存储

目录 一、存储基础1.1单机存储设备1.2单机存储的问题1.3分布式存储的类型 二、Ceph简介2.1Ceph 优势2.2Ceph 架构2.3Ceph核心组件OSD&#xff08;Object Storage Daemon&#xff0c;守护进程 ceph-osd&#xff09;PG&#xff08;Placement Group 归置组&#xff09;PoolMonitor…

SpringBoot错误: 找不到或无法加载主类

1.一般出现这种情况都是配置文件application.properties出现的问题 2.可以尝试 maven clean install 以及rebuild project 3.删除项目里.idea文件 重新导入至IDEA编辑器 选择Maven项目 配置好maven.xml 后重新导入

解决GitHub下载速度太慢问题的方法汇总(持续更新,建议收藏)

文章目录 前言一、使用 git clone --depth1 来下载二、修改host文件解决三、谷歌浏览器插件加速四、油猴插件和脚本五、gitclone.com六、Github 加速下载链接七、Github 镜像访问八、使用码云下载参考资料&#xff0c;感谢以下文章 前言 Github上下载仓库或者克隆仓库&#xf…

Docker基础——Centos7安装Docker

0.安装Docker Docker 分为 CE 和 EE 两大版本。CE 即社区版&#xff08;免费&#xff0c;支持周期 7 个月&#xff09;&#xff0c;EE 即企业版&#xff0c;强调安全&#xff0c;付费使用&#xff0c;支持周期 24 个月。 Docker CE 分为 stable test 和 nightly 三个更新频道…

「深度学习之优化算法」(十三)蝙蝠算法

1. 蝙蝠算法简介 (以下描述,均不是学术用语,仅供大家快乐的阅读)   蝙蝠算法(Bat Algorithm)是受蝙蝠回声定位的特性启发而提出的新兴算法,提出时间是2010年,虽然距今(2020)有近10年,但与其它的经典算法相比仍算一个新算法。算法也已有一定规模的研究和应用,但仍…
最新文章