(缺省参数)(函数重载)(引用)(内敛)(C++中的nullptr)

news2024/9/24 17:20:15

(缺省参数)&(函数重载)&(引用)&(内敛)&(atuo用法)&(C++中的NULL)

  • 1.缺省参数
    • 1.1缺省参数的概念
    • 1.2缺省参数的分类
    • 1.3缺省参数的注意事项
  • 2.函数重载
    • 2.1 重载的概念
    • 2.2 C++支持函数重载的原理--名字修饰
  • 3.引用
    • 3.1 引用给概念
    • 3.2 引用的使用规范
    • 3.3常引用
    • 3.4引用的使用场景
    • 3.5引用和指针的区别
  • 4. 内联
    • 4.1内联的概念
    • 4.2内联的特性
    • 4.3 inline与宏的区别
  • 5. C++中的nullptr

在这里插入图片描述

所属专栏:C“嘎嘎" 系统学习❤️
🚀 >博主首页:初阳785❤️
🚀 >代码托管:chuyang785❤️
🚀 >感谢大家的支持,您的点赞和关注是对我最大的支持!!!❤️
🚀 >博主也会更加的努力,创作出更优质的博文!!❤️
🚀 >关注我,关注我,关注我,重要的事情说三遍!!!!!!!!❤️

1.缺省参数

1.1缺省参数的概念

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实
参则采用该形参的缺省值,否则使用指定的实参。

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

在这里插入图片描述

  • 解释一下上述代码:
    缺省参数你可以理解成是一个替补成员,我们有正式成员的时候就不需要替补成员。反之如果我们没有正式成员的时候,这个时候就是我们的替补成员上场了。

1.2缺省参数的分类

  1. 全缺省参数
    顾名思义就是形参列表中的参数都是缺省参数。
void Func(int a = 10, int b = 20, int c = 30)
{
	cout<<"a = "<<a<<endl;
	cout<<"b = "<<b<<endl;
	cout<<"c = "<<c<<endl;
}
  1. 半缺省参数
    半缺省参数的意思不是说形参列表中的参数只有一半是缺省参数,而是说形参列表中即有缺省参数也有正常的参数。
void Func(int a, int b = 10, int c = 20)
{
	cout<<"a = "<<a<<endl;
	cout<<"b = "<<b<<endl;
	cout<<"c = "<<c<<endl;
}

1.3缺省参数的注意事项

  1. 半缺省参数必须从右往左依次来给出不能间隔着给。我们来看一下这个段代码:
void Func(int a = 100, int b , int c = 20)
{
	cout<<"a = "<<a<<endl;
	cout<<"b = "<<b<<endl;
	cout<<"c = "<<c<<endl;
}
  • 就像上面这段代码,我们的缺省参数在中间,二两边是正常的参数。
    首先结论就是,这个样子是不行的。因为,如果我们传参的时候会出现二义性:
    比如:
void Func(int a = 100, int b , int c = 20)
{
	cout<<"a = "<<a<<endl;
	cout<<"b = "<<b<<endl;
	cout<<"c = "<<c<<endl;
}
int main()
{
	Func(10,20);
	return 0;
}

此时我们Func(10,20)我们可以说10和a匹配,20和b匹配。我们也可以说10和b匹配,20和c匹配。我们可以说10和a匹配,20和c匹配。所以会出现二义性。为了避免这种现象出现,C++规定了半缺省参数必须从右往左依次来给出,不能间隔着给

  1. 缺省参数不能在函数声明和定义中同时出现
  • 如果我们在声明和函数都定义了缺省参数:
//a.h
void Func(int a = 10);
// a.cpp
void Func(int a = 20)
{}

万一我们函数的声明与定义中的缺省参数的值不一样了,这个时候改取哪一个值呢?就会出现二义性。

  • 如果我们只是在定义中定义缺省参数呢:
//a.h
void Func();
// a.cpp
void Func(int a = 20)
{}

//(main) a.cpp
#include "a.h";
int main()
{}

这个时候我们的主函数中包含了a.h,但是我们声明的时候没有定义缺省参数,这个时候我们在mian函数中使用这个Func函数的时候,我们没有传值的时候就不知道缺省参数的值了。
所以C++中定义了,函数的声明和定义中,只要声明定义缺省参数就行。

  1. 缺省值必须是常量或者全局变量
  2. C语言不支持(编译器不支持)

2.函数重载

在C语言中我们的函数名只能取一个,不能重名,也就是说如果我们要进行2个数相加,3个数相加……n+1个数相加,我们就要写上n个函数名,并且这些函数名都是不一样的。这下就有点为难我们了,如果这个n很大呢?那就的靠我们的想象力,和排列组合能力了,并且一点我们需要调用这些函数,我们还要记住这些函数名,显然如果函数不能重名的话,确实可能会给我们带来一些困难。

于是C++为了解决这种不方便的地方就有了函数重载的概念。

2.1 重载的概念

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

  1. 参数个数不一样
    在这里插入图片描述

  2. 参数类型不同
    在这里插入图片描述

  3. 类型顺序不同
    在这里插入图片描述

2.2 C++支持函数重载的原理–名字修饰

  • 为什么C++支持函数重载,而C语言不支持函数重载呢?
    在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。

在这里插入图片描述

  1. 实际项目通常是由多个头文件和多个源文件构成,而通过C语言阶段学习的编译链接,我们
    可以知道,【当前a.cpp中调用了b.cpp中定义的Add函数时】,编译后链接前,a.o的目标
    文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。那么
    怎么办呢?
  2. 所以链接阶段就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就
    会到b.o的符号表中找Add的地址,然后链接到一起。
  3. 那么链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的
    函数名修饰规则。
  4. 由于Windows下vs的修饰规则过于复杂,而Linux下g++的修饰规则简单易懂,下面我们使
    用了g++演示了这个修饰后的名字。
  5. 通过下面我们可以看出gcc的函数修饰后名字不变。而g++的函数修饰后变成【_Z+函数长度 +函数名+类型首字母】
  • 采用C语言编译器编译的后果
    *在这里插入图片描述

  • 采用C++编译器编译后结果
    在这里插入图片描述

  1. 通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修
    饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。
  2. 如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办
    法区分。

3.引用

3.1 引用给概念

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

使用语法:类型& 引用变量名(对象名)= 引用实体;

例如:
在这里插入图片描述

3.2 引用的使用规范

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体
  • 引用一旦引用一个实体,再不能引用其他实体我们可以把 int& c = a 理解成 int * const c = &a,这样我们就跟清楚的能够理解为什么引用一个实体化就不能引用其他实体了。

3.3常引用

我们能不能引用一个常量呢?

int main()
{
	int a = 10;
	int& c = a;
	return 0;
}
  • 上面这段代码是可行的,但是如果我们在int a的前面加上const呢?让他变成不可以修改的。
int main()
{
	const int a = 10;
	int& c = a;
	return 0;
}
  • 这个时候int& c = a还是正确的吗,显然不正确。a被const修饰后是不可修改的,现在我们给a取一个别名c但是c是可修改的,二c也是指向a这块空间的,现在矛盾来了,a不可修改,c可修改,二c也是指向a这块空间的,这显然会出错。所以想要得到解决方案就是让c也变成不可修改的,那么也加上const修饰。即:
int main()
{
	const int a = 10;
	const int& c = a;
	return 0;
}

同样的道理我们也可以个一个常量取别名:

int main()
{
	const int& c = 100;
	return 0;
}

3.4引用的使用场景

  1. 做参数
    我们对比一下我们之前写交换两个数:

C语言版本:

void Swap(int* a, int *b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

C++版本

void Swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = c;
}

这样一对比就可看出C++是更直观的。

  1. 做返回值
    我们来看接下来这段代码:
int& Add()
{
	int n = 0;
	n++;
	return n;
}

int main()
{
	int ret = Add();
	cout << ret << endl;
	return 0;
}
  • 这个结果是什么呢?
    在这里插入图片描述
  • 这里虽然输入的结果是我们预想到的,但是这样的写法并不是正确的。
    我们回顾一下我们的内存分为,栈区,堆区,静态区。我们的函数,局部变量都是存放在栈区的。栈区的特点是,进入作用域创建,出了后就会销毁。

在这里插入图片描述

  • 虽然输出的是1,那是因为虽然Add栈区被回收了,但是之前使用的时候我们有值已经存放进去了,只是回收空间,而里面值还没有被覆盖,如果被覆盖了输出的就是一个随机值了。

  • 注意:如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用
    引用返回,如果已经还给系统了,则必须使用传值返回。

3.5引用和指针的区别

  • 在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。
    但是我们的底层上引用和指针其实区别不大,并且引用也是开辟了空间的。

在这里插入图片描述
这里我们会发现,引用和指针在汇编中其实没多大区别。可以说是基本相同的。

引用和指针的不同点:

  1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
  2. 引用在定义时必须初始化,指针没有要求
  3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何
    一个同类型实体
  4. 没有NULL引用,但有NULL指针
  5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32
    位平台下占4个字节)
  6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  8. 引用比指针使用起来相对更安全

4. 内联

4.1内联的概念

  • 以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调
    用建立栈帧的开销,内联函数提升程序运行的效率。

在这里插入图片描述

如果在上述函数前增加inline关键字将其改成内联函数,在编译期间编译器会用函数体替换函数的
调用。

查看方式:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 此时我们就可以看到用来inline之后,函数是没有进行额外栈创建的,而是直接展开了。
    在这里插入图片描述

4.2内联的特性

  1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会
    用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运
    行效率。
  • 假如你有一个函数,它有10000行,如果我们强行的加上inline,那么在我们的汇编就会讲着10000行全部展开,而如果我们要多次进行使用这个函数,拿如果我们有100次调用这函数,拿我们全部展开是多少行呢?是100*10000行,这个时候我们的可执行程序的大小是不是就变大了啊。
    而如果我们不进行只能开,而是直接call这个函数,那么我们每次调用这个函数时候,只需要接收这个函数的地址就行了,每次接收这个地址我们就跳转到这个函数二外创建好的空间,直接进行使用了,而这个我们之展开了100+10000行,这样我们的可执行程序的大小是不是就变小啊。

  • 所以inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建
    议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不
    是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性

  1. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址
    了,链接就会找不到

4.3 inline与宏的区别

  • 宏优点:
    1.增强代码的复用性。
    2.提高性能。

  • 缺点:
    1.不方便调试宏。(因为预编译阶段进行了替换)
    2.导致代码可读性差,可维护性差,容易误用。
    3.没有类型安全的检查 。

  • C++有哪些技术替代宏?
    1.常量定义 换用const enum
    2.短小函数定义 换用内联函数

5. C++中的nullptr

  • C++98中的指针空值:在良好的C/C++编程习惯中,声明一个变量时最好给该变量一个合适的初始值,否则可能会出现
    不可预料的错误,比如未初始化的指针。如果一个指针没有合法的指向,我们基本都是按照如下
    方式对其进行初始化。

int* ptr = NULL;
int* str = 0;

NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:
在这里插入图片描述

  • 可以看到,NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。不论采取何
    种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦,比如

在这里插入图片描述

  • 也就是说NULL被认定为是整形了,但是程序本意是想通过f(NULL)调用指针版本的f(int*)函数,但是由于NULL被定义成0,因此与程序的
    初衷相悖。
    在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量,但是编译器
    默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void*)0。

于是为了区分C++11中引入了一个关键子nullptr;

  1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入
    的。
  2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
  3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。

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

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

相关文章

谈谈电商App的压测

背景 最近恰逢双十一&#xff0c;大大小小的电商app在双十一之前都会做一次压测&#xff0c;曾经在小公司工作的时候很想知道大公司是如何压测的&#xff0c;有什么高深的压测工具没&#xff0c;本文就来揭露一下 压测真相 在确认使用什么压测工具进行压测之前&#xff0c;我…

(※)力扣刷题-栈和队列-用栈实现队列

使用栈实现队列的下列操作&#xff1a; push(x) – 将一个元素放入队列的尾部。pop() – 从队列首部移除元素。peek() – 返回队列首部的元素。empty() – 返回队列是否为空。 说明: 你只能使用标准的栈操作 – 也就是只有 push to top, peek/pop from top, size, 和 is empt…

R6G alkyne, 6-isomer可在反应中作为底物或催化剂发挥作用

试剂 | 基础知识概述&#xff08;部分&#xff09;: 英文名&#xff1a;R6G alkyne, 6-isomer 分子式&#xff1a;C30H29N3O4 分子量&#xff1a;495.57 Ex &#xff1a;518nm Em&#xff1a;542nm 规格标准&#xff1a;10mg、25mg、50mg&#xff0c;可提供mg级以及kg级的…

系统架构师备考倒计时16天(每日知识点)

1.信息化战略与实施 2.UML图&#xff08;12个&#xff09; 3.结构化设计&#xff08;耦合&#xff09; 4.SMP与AMP的区别&#xff08;多核处理器的工作方式&#xff09; 多核处理器一般有SMP和AMP两种不同的工作方式: SMP(对称多处理技术)&#xff1a;将2颗完全一样的处理器封…

24---WPF缓存

一、什么是缓存&#xff1a; 1.缓存指的是将需要频繁访问的网络内容存放在离用户较近、访问速度更快的系统中&#xff0c;以提高内容访问速度的一种技术。缓存服务器就是存放频繁访问内容的服务器。 2.缓存就是一个临时存放区域--离用户比较近 二、作用--意义---如果系统出现故…

郭明錤修正预测:苹果第二代AirTag推迟2025年量产

10月19日&#xff0c;知名分析师郭明錤调整今年8月关于苹果第2代AirTag的预测&#xff0c;表示该产品量产时间从先前预测的2024年Q4延迟至2025年&#xff0c;并进一步推迟新款上市日期。 AirTag是苹果公司推出的一款蓝牙设备&#xff0c;配合苹果设备的“查找”APP&#xff0c…

【综述】Diffusion Models: A Comprehensive Survey of Methods and Applications

Diffusion Models: A Comprehensive Survey of Methods and Applications 论文&#xff1a;https://arxiv.org/abs/2209.00796 github&#xff1a;https://github.com/YangLing0818/Diffusion-Models-Papers-Survey-Taxonomy 目录 Diffusion Models: A Comprehensive Survey…

双指针——复写零

一&#xff0c;题目要求 给你一个长度固定的整数数组 arr &#xff0c;请你将该数组中出现的每个零都复写一遍&#xff0c;并将其余的元素向右平移。 注意&#xff1a;请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改&#xff0c;不要从函数返回任何东…

【Java基础面试三十一】、String a = “abc“; ,说一下这个过程会创建什么,放在哪里?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;String a “abc”; &am…

web:[极客大挑战 2019]HardSQL

题目 打开页面显示为 查看源代码没有发现其他的提示信息&#xff0c;随便尝试一下 错误 题目名为hardsql&#xff0c;先来尝试有无sql注入存在 尝试输入单引号输入 显示页面存在注入 这里按照常规思路继续使用order by函数和union select函数进行查询&#xff0c;但是页面没有…

019-第三代软件开发-Git提交规范

第三代软件开发-Git提交规范 文章目录 第三代软件开发-Git提交规范项目介绍Git提交规范分支规范Commit Message FormatHeaderBodyFooterRevert 总结一下 关键字&#xff1a; Qt、 Qml、 git、 Commit、 release 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个…

【三维重建】DreamGaussian:高斯splatting的单视图3D内容生成(原理+代码)

文章目录 摘要一、前言二、相关工作2.1 3D表示2.2 Text-to-3D2.3 Image-to-3D 三、本文方法3.1生成式 高斯 splitting3.2 高效的 mesh 提取3.3 UV空间的纹理优化 四. 实验4.1实施细节4.2 定性比较4.3 定量比较4.4 消融实验 总结&#xff08;特点、局限性&#xff09; 五、安装与…

【MySQL系列】- Select查询SQL执行过程详解

【MySQL系列】- Select查询SQL执行过程详解 文章目录 【MySQL系列】- Select查询SQL执行过程详解一、SQL查询语句的执行过程二、SQL执行过程详解2.1. 连接器2.2. 查询缓存2.3. 分析器2.4. 优化器2.5. 执行器 三、undo log 和 redo log作⽤3.1. redo log &#xff08;重做日志&a…

面试算法31:最近最少使用缓存

题目 请设计实现一个最近最少使用&#xff08;Least Recently Used&#xff0c;LRU&#xff09;缓存&#xff0c;要求如下两个操作的时间复杂度都是O&#xff08;1&#xff09;。 get&#xff08;key&#xff09;&#xff1a;如果缓存中存在键key&#xff0c;则返回它对应的值…

lunux查找占用内存前10的进程

1、使用Top命令查询进程 输入 top 命令&#xff0c;然后按下大写M按照内存MEM排序&#xff0c;按下大写P按照CPU排序。 2、查询占用CPU最高的前10个进程 ps aux|head -1;ps aux|grep -v PID|sort -rn -k 3|head 3、查询占用内存最大的前10个进程 ps aux|head -1;ps aux|grep …

Visual Studio Code官网下载、vscode下载很慢、vscode下载不了 解决方案

前言 开发界的小伙伴们对于Visual Studio Code开发环境来可以说非常熟悉了&#xff0c;但由于在Visual Studio Code官网的下载速度非常的慢&#xff0c;即便开了代理也是一样的很慢、甚至下载被中断&#xff0c;几乎不能下载。 解决方案 1、在Web浏览器上打开vscode官网&#…

日常中msvcp71.dll丢失怎样修复?分享5个修复方法

在 Windows 系统中&#xff0c;msvcp71.dll 是一个非常重要的动态链接库文件&#xff0c;它承载了许多应用程序和游戏的运行。如果您的系统中丢失了这个文件&#xff0c;那么您可能会遇到无法打开程序、程序崩溃或出现错误提示等问题。本文将介绍 5 个快速修复 msvcp71.dll 丢失…

最新视频/图集去水印小程序源码/步数小程序源码/王者战力小程序源码/红包封面小程序源码

自带多平台解析接口 短视频去水印图集水印小程序源码 &#xff0c;这是一款支持多种平台去水印的一款微信小程序源码 支持短视频去水印&#xff0c;还有图集去水印等。内含多平台去水印接口&#xff0c;响应的速度也是非常的快&#xff0c;这是一款非常值得推荐的一款小程序源…

2008-2021年上市公司实体企业金融化程度测算数据(原始数据+stata代码)

2008-2021年上市公司实体企业金融化程度测算&#xff08;原始数据stata代码&#xff09; 1、时间&#xff1a;2008-2021年 2、指标&#xff1a;股票代码、年份、交易性金融资产、衍生金融资产、发放贷款及垫款净额、可供出售金融资产净额、持有至到期投资净额、长期债权投资净…

【Java基础面试二十四】、String类有哪些方法?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;String类有哪些方法&…