C++入门:从C语言到C++的过渡(2)

目录

1.缺省参数

1.1缺省参数的概念

1.2缺省参数的分类及使用

1.3注意点

2.函数重载

2.1函数重载的定义

2.2函数重载的情况分类

2.3注意

2.4函数名修饰规则

3.引用

3.1引用的概念

3.2注意事项

3.3常引用

4.4引用的使用场景

4.4.1作为函数的参数

4.4.2做函数返回值

4.5传值和传引用

4.6引用和指针的联系与区别


1.缺省参数

1.1缺省参数的概念

缺省参数声明或定义函数时为函数的参数指定一个缺省值。在调用这个函数时,如果没有传入实参,则采用缺省值作为形参。

void print(int a = 0)
{
	cout << a << endl;
}
int main()
{
	print();//没有传参时,使用参数的默认值
    print(10);//传参时,使用指定的实参。
	return 0;
}

 输出结果: 0

                    10

1.2缺省参数的分类及使用

我们可以将缺省参数分为两类

  • 全缺省参数
void print(int a = 0,int b=3,int c=5)
{
	cout << a <<' ';
	cout << b <<' ';
	cout << c <<endl;
}

在使用上述代码中的全缺省参数的函数时,我们可以全部使用其给出的缺省参数,也可以从左到右给出实参。 

int main()
{
	print();
	print(7);
	return 0;
}

结果:0 3 5
           7 3 5 

  • 半缺省参数

半缺省参数必须从右向左依次给出,不可从左向右给,也不可间隔着给。

void print(int a,int b=3,int c=5)//a没有给出缺省值
{
	cout << a <<' ';
	cout << b <<' ';
	cout << c <<endl;
}

 

1.3注意点

在使用缺省参数时,我们不可在声明和定义中同时给出缺省参数,这是因为如果你同时给出了缺省值,编译器无法分辨你将缺省值给了谁。

因此,我们建议大家在声明函数时给出缺省值。 

另外,大家可能还有一个问题,为什么在使用采用了缺省值的函数时,实参必须从左往右给?为什么在给形参缺省值时,必须从右往左给呢?

问题1:在使用缺省参数时,我们的脑袋可以跳过第一个参数给第二个参数实参,但是编译器不是我们的脑袋,他没办法分辨,而且,再说了,换一个脑袋也不知道你想给第几个参数实参。

问题2:如果我们给形参缺省值时从左向右给,那么你在使用时给出实参,你给的是谁实参呢?是给了赋予了缺省值的参数实参,还是给了没有赋予缺省值的参数实参数呢?编译器又无法分辨了。

2.函数重载

在我们使用语言时,同一个词可能有很多个意思。

譬如背单词时一个单词有好多个意思......

我们希望也可以这样使用函数,因此,函数重载诞生了

2.1函数重载的定义

函数重载是函数的一种特殊情况,C++允许在同一作用域中声明同名函数,这些同名函数的形参列表(形参个数或形参类型或类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。

2.2函数重载的情况分类

  • 形参个数不同
void print(int a,int b=3,int c=5)//3个参数
{
	cout << a <<' ';
	cout << b <<' ';
	cout << c <<endl;
}
void print(int a, int b = 3)//两个参数
{
	cout << a << ' ';
	cout << b << ' ';
}
  • 形参类型不同
void print(int a, int b,)
{
	cout << a << ' ';
	cout << b << ' ';
}
void print(char a, char b,)
{
	cout << a << ' ';
	cout << b << ' ';
}
  • 形参类型顺序不同 
void print(int a, char b,)
{
	cout << a << ' ';
	cout << b << ' ';
}
void print(char a, int b,)
{
	cout << a << ' ';
	cout << b << ' ';
}

2.3注意

这里需要大家注意的是,缺省值不同不会构成重载,返回类型不同也不会构成重载

//返回类型不同
int Add(int a, int b)
{
	return a + b;
}
double Add(int a,int b)//error
{
	return a + b;
}
//缺省值不同
int Add(int a=1, int b=20)
{
	return a + b;
}
int Add(int a=1, int b=2)//error
{
	return a + b;
}

缺省值不同不会构成重载的原因一者是因为编译器调用时不知道调用哪个函数,二者需要大家了解函数名修饰规则

返回类型不同不会构成重载便需要大家了解函数名修饰规则了。

2.4函数名修饰规则

我们首先要知道编译与链接时就知道C/C++程序运行起来要经历的四个阶段:

预处理:头文件展开、宏替换、条件编译、去掉注释,生成 .i 的文件。.h的文件直接被展开。
编译: 语法检查(语法分析、语义分析、词法分析)、符号汇总、生成汇编代码,生成.s文件。
汇编: 把汇编代码转换为二进制机器码,形成符号表,生成.o文件。符号表里存放定义函数的地址信息。
链接: 合并目标文件、段表,符号表的合并和符号表的重定位,.o格式的目标文件合并到一起,生成.out/.exe文件。

    实际项目通常是由多个头文件和多个源文件构成,在上图中,main.c中调用了 sum.c中定义的sum函数,编译后链接前,main.c的目标文件中并没有Add的函数地址,因此sum是在sum.c中定义的,所以sum的地址在b.o中。那么应该怎么找到这个地址呢?

    链接阶段就是专门处理这种问题的,链接器在看到main.o调用了sum后,会到sumo的符号表中找sum的地址,然后链接到一起。

    在链接时,面对sum函数,链接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则。

下面我们可以看看在g++环境下编译的函数修饰规则

g++的函数修饰规则相对较简单:_Z+函数名长度+每个参数类型

因此,缺省值和返回值不同不会构成函数重载。

3.引用

3.1引用的概念

引用不是新定义一个变量,而是给已存在的变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间

打个比方:我本名叫小明,但我在CSDN上叫裤裤。小王和裤裤都是我。

其语法为:

int xiaoming = 3;
类型& 引用变量的名字 = 引用实际名;
int&        kuku     = xiaoming;

这里,我们先创建了一个叫xiaoming的变量,然后给他取了一个叫kuku的别名。而xiaoming和kuku实际上都是3.

通过打印它们的地址,我们发现它们的地址也是一样的,因此他们共用同一块内存空间。 

3.2注意事项

  • 由于引用变量和被引用的变量指向同一块空间,所以改变引用变量,被引用的变量也会改变。

这里将引用变量自增1,被引用的实体也自增了1.

  • 引用在定义时必须初始化 

  • 一个变量可以有多个引用
	int a = 3;
	int& ra=a;
	int& raa = a;
  • 一个引用一旦初始化一个实体,不可再引用别的实体。 
	int a = 3;
	int b = 5;
	int& ra=a;
	ra=b;//这时是赋值,而不是引用b
  • 无法引用类型不同的实体  

   

3.3常引用

可能大家对无法引用类型不同的实体有所疑惑,为什么要常量限定呢?

现在我们学习一下常引用。

先补充一个知识点:

如果权限是可读可写,那么我们可以在使用时将权限缩小为只读;

如果权限是只可读,那么我们在使用时就不可将权限扩大为可读可写。

简而言之,权限可以平移和缩小,但不可扩大。

使用const修饰的变量为常变量,常变量只可读,不可写。

我们可以通过const修饰引用让其变为常引用。这时引用变量就无法被修改了,根据我们刚刚说的有关权限的知识点,我们可以推导出这个结论:我们只能将常变量赋值给常引用(权限的平移),不能将常变量赋值给引用(权限的扩大)。

	const int a = 10;//只可读
	int& ra = a;//报错  权限不可扩大为可读可写
	const int& ra = a;//正确,权限的平移  可读->可读
	int& b = 10;//报错,权限不可扩大 10为可读不可写,b为可读可写
	const int& b = 10;//正确,权限的平移

现在我们补充一个知识点,类型不同的赋值会发生类型转换,而类型转换会产生临时变量,而临时变量具有常性,即临时变量只可读。

 因此,我们可以写出如下代码:

	double d = 12.34;
	int& rd = d;//报错,d类型转化产生只可读的临时变量,可读的权限不可扩大为可读可写。
	const int& rd = d;//不报错,权限的平移

在学习常引用时,我需要大家再清晰一点:

之所以在使用引用时需要注意权限的大小,是因为它操纵的是一块空间,我们可以在一个可读可写的空间中进行读写操作,但是我们无法在只可读的空间中进行写的操作。但是,我们却可以将只可读的空间中的内容拿出来赋值给一个可读可写的空间。  

4.4引用的使用场景

4.4.1作为函数的参数

由于引用操作的是同一块空间,因此我们可以作为函数的参数进行传递,这样可以达到传指针一样的效果。

int swap(int& a, int& b)
{
	int tmp = 0;
	tmp = a;
	a = b;
	b = tmp;
}

4.4.2做函数返回值

做函数返回值一定要注意变量的生命周期,要保证返回的变量在函数销毁时生命周期还没有结束,否则可能出现野指针的问题。 

int& Count()
{
	static int n = 0;
	n++;
	return n;
}

在这里可以再给大家拓展一个知识点:静态变量只能初始化一次,若出现多次初始化语句,则会在编译时跳过除第一句之外的初始化语句。 

现在给大家给出一个问题:

int& Add(int a, int b)
{
	int c = a + b;
	return c;
}
int main()
{
	int& ret = Add(1, 2);
	Add(3, 4);
	cout << ret << endl;
	return 0;
}//输出什么

答案是:7 

这是因为我们采用了引用返回的方式,而c在函数栈帧销毁时也跟着被销毁了。

而我们在第二次调用Add()函数时,会在原来第一次调用Add()函数时调用的空间上重新建立栈帧。

所以我们返回值的c就被覆盖掉了,而ret指向的是c的空间,因此ret的值也发生改变了。

因此这样的情况下我们传值返回即可,传值返回的返回值会在函数栈帧被销毁前放入寄存器。

4.5传值和传引用

以值作为参数或者返回值类型,在传参或者返回期间,函数不会直接传递实参或者将变量本身直接返回,而是拷贝实参形成形参或者返回变量的一份临时拷贝(放在寄存器)。因此用值作为参数或者返回值类型的效率会比较低。

4.6引用和指针的联系与区别

引用的底层实现和指针其实没有区别。

int main()
{
	int a = 10;
	int& ra = a;
	ra = 20;
	int* pa = &a;
	*pa = 20;
	return 0;
}

现在我们观察一下这段代码的汇编:

但引用和指针还是有一定区别的

1.引用是变量的别名,指针是变量的地址

2.引用必须初始化,指针建议初始化

3.引用初始化后不可修改对象,但指针可以

4.引用的大小为引用类型的大小,指针要看平台。

5.没有多级引用,但是有多级指针

6.引用更安全

码字不易,给裤裤一个三连关注评论叭~~

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

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

相关文章

等保三级 腾讯云控制台检查项设置

1、地址限制 2、角色里加三权用户&#xff08;查看日志权限&#xff09; 3、登录失败处理和超时退出 4、密码复杂度和口令有效期 5、双因素验证 6、操作审计

怎么快速批量导出文本二维码?文件批量生码的方法和步骤

随着互联网的快速发展&#xff0c;二维码的应用也越来越广泛&#xff0c;现在很多二维码会用来展示物品信息&#xff0c;将编辑好的文字内容生成二维码之后&#xff0c;让其他人通过扫码的方式来获取相关内容。那么当有多条信息时&#xff0c;有什么方法能够一次批量生成二维码…

ctfhub中的SSRF的相关例题(下)

目录 URL Bypass 知识点 相关例题 数字IP Bypass 相关例题 方法一&#xff1a;使用数字IP 方法二&#xff1a;转16进制 方法三&#xff1a;用localhost代替 方法四&#xff1a;特殊地址 302跳转 Bypass ​编辑 关于localhost原理: DNS重绑定 Bypass 知识点&…

第 398 场 LeetCode 周赛题解

A 特殊数组 I 模拟&#xff1a;遍历数组判断是否是一个特殊数组 class Solution { public:bool isArraySpecial(vector<int>& nums) {int r 0;while (r 1 < nums.size() && nums[r 1] % 2 ! nums[r] % 2)r;return r nums.size() - 1;} };B 特殊数组 I…

打包要求 minCompileSdk 使用指定版本及以上

我当前的 compileSdkVersion 30&#xff0c;因为依赖了 androidx.core:core:1.9.0 它要求最低 compileSdkVersion 33。 那么如果我不想升级 compileSdkVersion 应该怎么办&#xff1f; 答&#xff1a;当然是降低 core:core 版本&#xff01; 看看谁依赖了这两个版本 android…

SpringCloud微服务04-Elasticsearch-DSL查询-聚合

一、Elasticsearch 搜索引擎&#xff0c;响应速度非常快&#xff0c;特别是对大数据量的情况 1.初始elasticsearch 如果只需要商品搜索&#xff0c;百度这种搜索网站&#xff0c;只需要第二个就够了 docker部署&#xff1a;day08-Elasticsearch - 飞书云文档 (feishu.cn) e…

有趣的css - 移形换位加载动画

大家好&#xff0c;我是 Just&#xff0c;这里是「设计师工作日常」&#xff0c;今天分享的是一个移形换位动态加载小动效&#xff0c;适用于 app 列表加载&#xff0c;页面加载或者图片懒加载等场景。 最新文章通过公众号「设计师工作日常」发布。 目录 整体效果核心代码html…

python基础之循环

目录 1.while 循环 2.for循环 3.for-else 和 while-else 4.关键字break和continue 1.while 循环 语法结构 while 条件语句:代码 解释&#xff1a;不断循环&#xff0c;如果条件语句为真&#xff0c;则执行代码&#xff0c;直到条件语句为假。假设条件语句一直为真&#xff0…

智能体(Agent)详细精讲

1.什么是智能体 智能体&#xff08;Agent&#xff09;是一种由大规模语言模型&#xff08;如GPT-4或本地模型&#xff09;驱动的先进系统&#xff0c;能够执行多种复杂任务。通过引入智能体&#xff0c;企业和个人可以实现自动化处理和高效管理各种事务。 智能体的核心是其“大…

ATmega328P加硬件看门狗MAX824L看门狗

void Reversewdt(){ //硬件喂狗&#xff0c;11PIN接MAX824L芯片WDIif (digitalRead(11) HIGH) {digitalWrite(11, LOW); //低电平} else {digitalWrite(11, HIGH); //高电平 }loop增加喂狗调用 void loop() { …… Reversewdt();//喂狗 }

❤Element的使用element

❤Element的使用 1、input输入框 禁止自动补全和下拉提示 input 输入框在输入后浏览器会记录用户输入的值&#xff0c;在下次输入的时候会将记录的值提示在输入框的下面&#xff0c;当输入框是密码的时候&#xff0c;这样可以看见上次输入的密码&#xff0c;这样用户体验不好…

2024全新Langchain大模型AI应用与多智能体实战开发

2024全新Langchain大模型AI应用与多智能体实战开发 LangChain 就是一个 LLM 编程框架&#xff0c;你想开发一个基于 LLM 应用&#xff0c;需要什么组件它都有&#xff0c;直接使用就行&#xff1b;甚至针对常规的应用流程&#xff0c;它利用链(LangChain中Chain的由来)这个概念…

[Linux]Crond任务调度以及at任务调度

一.crond任务定时调度 crond是反复检测执行的&#xff0c;一个任务结束后&#xff0c;在所规定的时间之后会再次执行 crontab 指令可以给系统分配定时任务 crontab -e 进入编辑页面&#xff0c;设定任务 crontab -l 查看已有定时任务 crontab -r 删除所有任务 编辑时&#xff…

深度学习之基于MTCNN+Facenet的人脸识别身份认证系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 随着信息技术的快速发展&#xff0c;身份认证技术在日常生活和工作中的重要性日益凸显。传统的…

【全部更新完毕】2024电工杯B题详细思路代码成品文章教学:大学生平衡膳食食谱的优化设计及评价

大学生平衡膳食食谱的优化设计及评价 摘要 大学阶段是学生获取知识和身体发育的关键时期&#xff0c;也是形成良好饮食习惯的重要阶段。然而&#xff0c;当前大学生中存在饮食结构不合理和不良饮食习惯的问题&#xff0c;主要表现为不吃早餐或早餐吃得马虎&#xff0c;经常食用…

Python文件和数据格式化-课后作业[python123题库]

文件和数据格式化-课后作业 一、单项选择题 1、文件句柄f&#xff0c;以下是f.seek(0)作用的是&#xff1a;‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪…

如何从http免费升级到https

使用https协议开头是为了在用户访问网站时提供更安全的网络环境。相比http&#xff0c;使用https有数据加密、身份验证、保护隐私、搜索引擎优化等优势。一般获取https证书&#xff0c;则需要支付费用给证书颁发机构&#xff08;CA&#xff09;。还有一些免费的证书证书颁发机构…

嵌入式单片机启动地址映射关系

一、内核只会从0地址启动 1.0地址第一个字是sp栈指针,第二个字是Reset_Handler入口,参考图1中启动代码中的中断向量表。具体使用流程参考图2(参考自野火) 图1 图2 2.0地址映射以后,软件上使用0地址访问的空间是映射到的器件的空间 3.0地址映射只会影响单个器件上的地址,…

知识图谱数据预处理笔记

知识图谱数据预处理笔记 0. 引言1. 笔记1-1. \的转义1-2. 特殊符号的清理1-3. 检查结尾是否正常1-4. 检查<>是否存在1-5. 两端空格的清理1-6. 检查object内容长时是否以<开始 0. 引言 最近学习知识图谱&#xff0c;发现数据有很多问题&#xff0c;这篇笔记记录遇到的…

数据可视化

目录 数据可视化: 常见的数据可视化库: Echarts 使用五步曲 Echarts 相关配置 数据可视化: 应对现在数据可视化趋势,越来越多企业需要在很多场景(营销数据,生产数据,用户数据)下使用,可视化图表来展示体现数据,让数据更加直观,数据特点更加突出 主要目的:借助于…