C++:缺省参数|函数重载|引用|const引用

欢迎来到Harper·Lee的学习笔记!
博主主页传送门:Harper·Lee的博客主页
想要一起进步的uu可以来后台找我哦!

一、缺省参数

1.1 缺省参数的定义

缺省参数:是声明或定义函数时为函数的参数指定⼀个缺省值。在调用该函数时,如果没有指定实参则采⽤该形参的缺省值,否则使用指定的实参。(有些地方把缺省参数叫做默认参数)

#include <iostream>
using namespace std;
void Func(int a = 0)//行参的后面赋一个常量值或者全局变量值,指定参数值
{
	cout << a << endl;
}
int main()
{
	Func(); // 没有传参时,使⽤参数的默认值
	Func(10); // 传参时,使⽤指定的实参
	return 0;
}

1.2 缺省参数的分类

1.2.1 全缺省参数

全缺省:全部的行参参数都给缺省值。

#include <iostream>
using namespace std;
// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)//每个参数都有缺省值
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}

int main()
{
	Func1();//不传参数,10,20,30
	Func1(1);//传一个参数,1,20,30
	Func1(1, 2, 3);//1,2,3
    //Func1( ,1, );这种形式不可以,因为是本贾尼规定的

	return 0;
}

运行结果:
image.png

1.2.2 半缺省参数

半缺省:部分形参给缺省值。C++规定半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值。

#include <iostream>
using namespace std;
// 半缺省
void Func2(int a, int b = 10, int c = 20)//半缺省即部分缺省
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}

int main()
{
    //Func2();//不传参数会报错
	Func2(100);//
	Func2(100, 200);
    Func2(100,200,300);

	return 0;
}

运行结果:
image.png

1.2.3 缺省参数的应用

缺省参数的应用:比如在创建栈的时候,经常会出现初始化的时候考虑扩容, 不确定要扩多大的空间,因此可以使用缺省参数:不确定扩多大空间,可以通过半缺省使用原先的缺省值,确定扩容的空间时,就直接空间容量作为传入参数。初始化栈的时候就扩容了,效率很高。
缺省参数就像现实中的备胎舔狗一样,别人需要它是才会想到它。

1.2.4 缺省参数的注意点

  1. 带缺省参数的函数调用:C++规定必须从左到右依次给实参,不能跳跃给实参。
#include <iostream>
using namespace std;

void Func2(int a, int b = 10, int c = 20)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}
int main()
{
    Func2(100, ,300);//error
    return 0;
}
  1. 缺省值必须是常量或者全局变量。
  2. C语言编译器不支持缺省。
  3. 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值。
//test.h
void Func1(int a = 10);//声明
// test.cpp
void Func1(int a = 20)//定义
{}//error
//如果生命与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。


//test.h
void Func2(int a = 10);//声明中赋缺省值
// test.cpp
void Func2()//定义中没有赋缺省值
{}//right

二、函数重载

2.1 函数重载的概念

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

2.2 函数重载的分类

2.2.1 参数类型不同

#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int a, int b)
{
	return a + b;
}
double Add(double a, double b)
{
	return a + b;
}
int main()
{
	cout << Add(1, 2) << endl;
	cout << Add(1.1, 2.2) << endl;
	return 0;
}

运行结果:
image.png

2.2.2 参数个数不同

// 2、参数个数不同
#include<iostream>
using namespace std;//展开std
void f()
{
	cout << "f()" << endl;
}
void f(int a)
{
	cout << "f(int a)" << endl;
}
int main()
{
	f();//调用的是没有参数的f函数
	f(1);//调用的是有参数f函数
	return 0;
}

运行结果:
image.png

2.2.3 参数类型顺序不同

// 3、参数类型顺序不同
#include<iostream>
using namespace std;//展开std
void  f1(int a, double b)
{
	cout << "f1(int a, double b)" << endl;
}
void  f1(double a, int  b)
{
	cout << "f1(double a, int  b)" << endl;
}
int main()
{
	f1(1, 2.0);
	f1(1.0, 2);
	return 0;
}

运行结果:
image.png

2.2.4 函数构成重载但调用歧义

// 下⾯两个函数构成重载,但是f()调⽤时,会报错,存在歧义,编译器不知道调⽤谁
#include<iostream>
using namespace std;//展开std
void f3()
{
	cout << "f()" << endl;
}
void f3(int a = 10)//缺省参数
{
	cout << "f(int a)" << endl;
}
int main()
{
	f3();//error函数调用看的是行参,与缺省参数没有关系!因此发生歧义!!!
	f3(2);//给了参数就明确说明是要调用第二个函数
	return 0;
}

错误列表:
image.png
无参调用时,就没有办法进行区分了,因此不要写无参数函数和全缺省函数重载!!!最好的解决办法就是使用域隔离,此时两者没有在同一个作用域里,不再是函数重载了。

2.2.5 返回值不同不构成重载

#include<iostream>
using namespace std;//展开std
//返回值不同不能作为重载条件,因为调用时也⽆法区分
void fxx()
{}

int fxx()
{
	return 0;
}

假设返回值不同可以构成重载,但是如何判定调用的是有参函数还是无参函数?所以返回值不同不能作为重载条件,因为调用时也无法区分。

三、引用

3.1 引用的概念

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

类型&引用别名=引用对象;

#include<iostream>
using namespace std;
int main()
{
	int a = 0;
	int& b = a;//引⽤:b是a的别名
	int& c = b;//也可以给别名b取别名,c相当于还是a的别名

	++c;//就是++b,也就是++a

	cout << &a << endl;//&代表取地址
	cout << &b << endl;
	cout << &c << endl;

	cout << a << endl;//&代表取地址
	cout << b << endl;
	cout << c << endl;

	return 0;
}

运行结果:
image.png

3.2 引用的特性

3.2.1 引用定义时必须初始化

	int a = 1;
	int& b = a;//right,引用b取别名,是a的别名
	int& rb;//error,取别名,但是不知道是谁的别名

3.2.2 别名可以取别名

	int a = 1;
	int& b = a;//b是a的别名
	int& c = b;//c是别名b的别名

3.2.3 一个变量可有多个引用

一个变量我们可以起多个别名

int a = 0;
// 引⽤:b和c是a的别名
int& b = a;
int& c = a;

3.2.4 引用一旦引用一个实体,就不能引用其他实体

引用只能给一个变量当别名,不能给多个变量当别名。

	int a = 2;
	int m = 3;
	int& b = a;//这里b引用了实体a
	int& b = m;//error,这里b又引用实体m,error

3.2.5 C++引用不能改变指向

C++的引用不能替代指针!!!

#include<iostream>
using namespace std;

int main()
{
	int a = 1;
	int& b = a;//引用b取别名,是a的别名
	int d = 20;
	b = d;//这是一个赋值,因为不能改变指向
	printf("b = %d\n", b);
	cout << &a << endl;
	cout << &b << endl;
	cout << &d << endl;
	return 0;
}

运行结果:
image.png

3.3 引用的运用

3.3.1 作为函数参数

引用传参与指针传参功能相似,引用传参减少拷贝效率,改变引用对象,同时也可以改变被引用对象。
解决了C语言中行参无法影响实参的问题,也比指针传参相对更加方便。

#include<iostream>
using namespace std;
//现在的写法
void Func(int& x)//引用作为函数参数,x是a的别名
{
	int m = 20;
	x = m;//x被改变,实体a也被改变(引用对象改变了,被引用对象也改变了)
	cout << x << endl;
}
//以前的写法
void Func1(int* x)
{
    int m = 20;
    *x = m;
 	cout << x << endl;   
}
int main()
{
	int a = 2;
	Func(a);
    //Func1(&a);
	return 0;
}

运行结果:
image.png
举个例子:引用可以不通过指针(地址),就可以作为函数参数,改变实参。

#include<iostream>
using namespace std;
//C语言中指针类型的Swap函数
void Swap1(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
//C++中引用形式的Swap函数
void Swap2(int& rx, int& ry)
{
	int tmp = rx;
	rx = ry;
	ry = tmp;
}
int main()
{
	int x = 2, y = 4;
	Swap1(&x, &y);..是用来指针
	cout << "x = " << x << "," << "y = " << y << endl;

	int m = 3, n = 7;
	Swap2(m, n);//没有使用指针
	cout << "m = "<< m << "," << "n = " << n << endl;
	return 0;
}
//分析:在Swap2函数中,rx和ry分别是m和n的别名,用的是同一块空间,
//因此rx和ry改变就相当于m和n的改变

运行结果:
image.png

3.3.2 作为函数返回值

引用作为返回值的场景相对复杂,可以减少拷贝效率,改变引用对象,同时也可以改变被引用对象。这里简单一提,类和对象中深入讨论。
image.png???
错误示范:

#include<iostream>
using namespace std;
int& Func()
{
	int a = 0;
	return a;//返回后,函数栈桢被销毁,返回引用,相当于返回一个野指针
}

前两条总结:引用传参和引用做返回值中 1. 减少拷贝提高效率;2. 改变引用对象时;3.改变被
引用对象。

3.4 引用和指针的区别

  1. 语法上:引用是给变量取别名,不开空间,它和它引用的对象是同一个空间。指针是存储一个变量的地址,需要开空间。
  2. 初始化:引用在定义的时候需要初始化,指针定义的时候为了避免野指针,建议初始化。
  3. 对象改变:引用在初始化时引用一个对象后,就不能再引用其他对象;指针可以不断地改变指向的对象。
  4. 访问对象:引用可以直接访问对象,指针需要解引用才能访问对象。

#include<iostream>
using namespace std;
int main()
{
	int a = 0;
	int* p = &a;
	*p = 1;//指针需要解引用才能访问对象

	int& ra = a; 
	ra = 2;//引用可以直接访问对象

	return 0;
}
  1. 安全性:指针容易出现空指针野指针,引用相对安全些。
  2. sizeof中含义不同:引用结果为引用类型的大小;指针始终是地址空间所占字节数(32位平台下4Byte,64位平台下8Byte)
  3. 引用的安全是相对安全。
//错误引用
int& Func()
{
    int a = 0; 
    return a;
}//返回一个类似野指针的东西,相当于是空引用
  1. 间接的一个空引用。
int* ptr = NULL;//地址是0
int& rb = *ptr;
//rb++;//error,程序异常结束,这里相当于空引用
  1. 转到反汇编:这里是内存,访问内存时image.png???不懂的指令:百度

嵌入式驱动开发比较要求底层像汇编之类的。
image.png

四、const引用

4.1 const引用示范及权限变化

  1. 由const修饰的对象不能像普通对象那样直接引用,需要使用const进行引用。
  2. const引用的权限变化:有权限平移、权限缩小,但是不能权限放大。
  3. const引用可以给常量取别名。
  4. 临时对象:编译器需要⼀个空间暂存表达式的求值结果,这个空间就是临时创建的⼀个未命名的对象的空间。C++中把这个未命名对象叫做临时对象,并规定临时对象具有常性。
  5. 表达式被存放在临时变量中,对临时对象引用取别名需要const修饰。
int main()
{
	const int a = 10;
	int& ra = a;        //error,权限放大

	const int b = 20;
	const int& rb = b;  //right,权限平移

	int c = 30;
	const int& rc = c;  //right,权限缩小
	++c;                //right
	++rc;               //error,c和rc是同一个地址不同的权限

	const int& rd = 40; //right,const引用可以给常量取别名

	int& re = (a + b);  //error,C++规定临时对象具有常性,这里,权限放大,const修饰即可
	const int& rf = (a + b);//right
    int rg = (a + b);//拷贝,不存在权限放大
    //a+b被存放在临时对象中,对临时对象引用取别名需要const修饰
    
	return 0;
}

4.2 权限放大和赋值的区别

权限放大和缩小在指针和引用中才会有,复制拷贝并没有权限变化。

const int a = 10;   //a:只读
int&  ra = a;//error,ra可读可写,权限放大

const int b = 20;//b只读
int rb = b;  //right,rb赋值拷贝,可读可写
//权限放大和缩小在指针和引用中才会有

4.3临时对象的产生

4.3.1 表达式结果产生临时对象

分析:a+b表达式的结果被存放在临时对象中,rf引用的对象是这个临时对象,但是临时对象具有常性,因此需要const修饰。

#include<iostream>
using namespace std;
int main()
{
    int a = 10;
    int b = 20;
    const int& rf = (a + b);//right,
    //a+b表达式的结果被存放在临时对象中,rf引用的对象是这个临时对象
    //但是临时对象具有常性,因此需要const修饰
    
    return 0;
}

4.3.2 隐式类型转换成临时对象(const修饰引用临时对象)

分析:rii 也是同理,引用的是临时对象,需要const修饰。

#include<iostream>
using namespace std;
int main()
{
	double d = 12.34;
	int i = d;//这里是通过了隐式类型转换,中间产生一个int临时对象存储d,i=12
	int& ri = d;          //error
	const int& rii = d;   //right,rii引用d,实际是引用的d的临时对象i

	return 0;
}

4.3.3 提升、转换等会产生临时对象

4.4 const引用总结

const引用总结:可以引用const修饰的对象、也可以引用普通对象、还可以引用临时对象。临时对象的生命周期就与引用有关系,引用销毁,临时对象才会销毁。它的价值主要体现在函数传参里面。
喜欢的uu记得三连支持一下哦!
在这里插入图片描述

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

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

相关文章

MYSQL数据库建表规则及注意事项

数据类型以及应用场景 数值类型 TINYINT&#xff1a;使用在 0~1 SMALLINT&#xff1a;使用在2~10 INT&#xff1a;常用 BIGINT&#xff1a;使用在用户ID等更大范围的整数 DECIMAL&#xff1a;用于存储精确的小数。常用于需要高精度计算的场景&#xff0c;如金融数据处理。 日期…

【UE5.3】笔记10-时间轴的使用

时间轴 右键--Add Timeline(在最下面) --> 双击进入时间轴的编辑界面&#xff1a; 左上角可以添加不同类型的轨道&#xff0c;可以自定义轨道的长度&#xff0c;单位秒&#xff0c;一次可以添加多个 可以通过右键添加关键帧&#xff0c;快捷键&#xff1a;shift鼠标左键按…

JMH325【剑侠情缘3】第2版80级橙武网游单机更稳定亲测视频安装教学更新整合收集各类修改教学补丁兴趣可以慢慢探索

资源介绍&#xff1a; 是否需要虚拟机&#xff1a;是 文件大小&#xff1a;压缩包约14G 支持系统&#xff1a;win10、win11 硬件需求&#xff1a;运行内存8G 4核及以上CPU独立显卡 下载方式&#xff1a;百度网盘 任务修复&#xff1a; 1&#xff0c;掌门任务&#xff08…

MMII 的多模态医学图像交互框架:更直观地理解人体解剖结构和疾病

医生在诊断和治疗过程中依赖于人体解剖图像&#xff0c;如磁共振成像&#xff08;MRI&#xff09;&#xff0c;难以全面捕捉人体组织的复杂性&#xff0c;例如组织之间的空间关系、质地、大小等。然而&#xff0c;实时感知有关患者解剖结构和疾病的多模态信息对于医疗程序的成功…

在mysql中delete和truncated的相同点和区别点

相同点 删除数据&#xff1a;两者都会删除表中的数据。影响数据&#xff1a;两者都不删除表结构&#xff0c;只影响表中的数据。 区别点 操作方式&#xff1a; DELETE&#xff1a;逐行删除数据&#xff0c;可以使用 WHERE 子句来指定删除的条件。如果不加 WHERE 子句&#…

R包:ggsci期刊配色

介绍 不同期刊配色大多数时候不一样&#xff0c;为了更好符合期刊图片颜色的配色&#xff0c;有人开发了ggsci这个R包。它提供以下函数&#xff1a; scale_color_palname() scale_fill_palname() 对应不同期刊的color和fill函数。 导入数据R包 library("ggsci")…

LAZYNVIM学习使用笔记

文章目录 1. 前言VIM的模式快捷键参考 1. 前言 习惯使用vscode进行代码编辑&#xff0c;无意中刷到lazynvim&#xff0c;感觉功能强大&#xff0c;于是下载、安装&#xff0c;学习使用一下&#xff0c;本篇主要记录学习使用lazynvim的一些要点&#xff0c;防止遗忘。 持续更新…

Unity 打包的安卓APK在模拟器运行一会卡死

Unity 安卓APK模拟器运行一会卡死 如题&#xff0c;unity在模拟器上运行安卓apk挂机一会就卡死&#xff0c;在真机上没问题。因为打包时勾选了这个帧率优化选项&#xff0c;2019.2之后的功能&#xff0c;最坑的时打包时默认勾选&#xff0c;所以使用这个版本打包时&#xff0c…

文献阅读(1)——深度强化学习求解车辆路径问题的研究综述

doi&#xff1a; 10.3778/j.issn.1002-8331.2210-0153 深度强化学习求解车辆路径问题的研究综述 (ceaj.org) 组合最优化问题&#xff08; combinatorial optimization problem&#xff0c; COP &#xff09; 日常生活中常见的 COP 问题有旅行商问题&#xff08;traveling sale…

微调Qwen2大语言模型加入领域知识

这里写自定义目录标题 试用Qwen2做推理安装LLaMA-Factory使用自有数据集微调Qwen2验证微调效果 试用Qwen2做推理 参考&#xff1a;https://qwen.readthedocs.io/en/latest/getting_started/quickstart.html from transformers import AutoModelForCausalLM, AutoTokenizer de…

NI 5G大规模MIMO测试台:将理论变为现实

目录 概览引言MIMO原型验证系统MIMO原型验证系统硬件LabVIEW通信系统设计套件&#xff08;简称LabVIEW Communications&#xff09;CPU开发代码FPGA代码开发硬件和软件紧密集成 LabVIEW Communications MIMO应用框架MIMO应用框架特性单用户MIMO和多用户MIMO基站和移动站天线数量…

作业/数据结构/2023/7/10

1.实现单向链表队列的&#xff0c;创建&#xff0c;入队&#xff0c;出队&#xff0c;遍历&#xff0c;长度&#xff0c;销毁。 main.c #include "head.h"int main(int argc, const char *argv[]) {//创建链式队列queue_ptr QLcreate_queue();//入栈push(QL, 1000)…

OpenGL3.3_C++_Windows(29)

Demo exposure 0.1f exposure 5.0f HDR色调映射 问题&#xff1a;有多个亮光源使这些数值总和超过了1.0&#xff0c;颜色值会被约束在1.0&#xff0c;从而导致场景混成一片&#xff0c;难以分辨&#xff1a;色调映射&#xff1a;用更大范围的颜色值渲染从而获取大范围的黑暗…

手搓前端day1

断断续续的学了些前端&#xff0c;今天开始写写代码&#xff0c;就当是记录一下自己前端的成长过程 效果&#xff1a; 写了点css&#xff0c;实现了简单的前端页面的跳转 文件目录 代码如下&#xff1a; styles.css body{margin: 0;padding: 0;}header{background-color: bl…

从0-1搭建一个web项目(路由目录分析)详解

本章分析vue路由目录文件详解 ObJack-Admin一款基于 Vue3.3、TypeScript、Vite3、Pinia、Element-Plus 开源的后台管理框架。在一定程度上节省您的开发效率。另外本项目还封装了一些常用组件、hooks、指令、动态路由、按钮级别权限控制等功能。感兴趣的小伙伴可以访问源码点个赞…

vue前端实现导出页面为word(两种方法)

将vue页面导出为word文档&#xff0c;不用写模板&#xff0c;直接导出即可。 第一种方法(简单版) 第一步&#xff1a;安装所需依赖 npm install html-docx-js -S npm install file-saver -S第二步&#xff1a;创建容器&#xff0c;页面使用方法 注意&#xff1a;在当前页面引…

对于多个表多个字段进行查询、F12查看网页的返回数据帮助开发、数据库的各种查询方式(多对多、多表查询、子查询等)。

对于多个表多个字段进行查询、F12查看网页的返回数据帮助开发、数据库的各种查询方式&#xff08;多对多、多表查询、子查询等&#xff09;。 一、 前端界面需要展现多个表的其中几个数据的多表查询。1. 三个表查询其中字段返回&#xff1a;&#xff08;用一下sql语句&#xff…

论文翻译 | (TAKE A STEP BACK) 后退一步:在大型语言模型中通过抽象来调用推理

摘要 我们介绍了STEP-BACK提示&#xff0c;这是一种简单的提示技术&#xff0c;使LLM能够进行抽象&#xff0c;从而从包含特定细节的实例中派生高级概念和第一原则。使用概念和原则来指导推理&#xff0c;LLM显着提高了他们遵循正确推理路径的能力。我们使用PaLM-2L、GPT-4和Ll…

3102.力扣每日一题7/9 Java(TreeMap)

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;算法练习关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 目录 TreeMap详解 解题思路 解题方法 时间复杂度 空间复杂度 Code T…

imx6ull/linux应用编程学习(16)emqx ,mqtt创建连接mqtt.fx

在很多项目中都需要自己的私人服务器&#xff0c;以保证数据的隐私性&#xff0c;这里我用的是emqx。 1.进入emqx官网 EMQX&#xff1a;用于物联网、车联网和工业物联网的企业级 MQTT 平台 点击试用cloud 申请成功后可得&#xff1a;&#xff08;右边的忽略&#xff09; 进入…