void Func(int a = 100, int b , int c = 20)
{
	cout<<"a = "<

此时我们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++支持函数重载的原理–名字修饰

在这里插入图片描述

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

3.引用

3.1 引用给概念

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

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

3.2 引用的使用规范

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体

3.3常引用

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

int main()
{
	int a = 10;
	int& c = a;
	return 0;
}
int main()
{
	const int a = 10;
	int& c = a;
	return 0;
}
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;
}

在这里插入图片描述

3.5引用和指针的区别

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

引用和指针的不同点:

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

4. 内联

4.1内联的概念

在这里插入图片描述

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

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

在这里插入图片描述

在这里插入图片描述

4.2内联的特性

  1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会
    用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运
    行效率。
  1. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址
    了,链接就会找不到

4.3 inline与宏的区别

5. C++中的nullptr

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

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

在这里插入图片描述

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

  1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入
    的。
  2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
  3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。
  • 相关阅读:
    Express-05
    OS - 操作系统实战 - 学习/实践
    Java实现模拟键盘和鼠标操作
    javaweb-响应字符数据
    Python交叉验证实现
    【32C++提高编程----3、STL入门篇】
    Kivy打包apk教程(含kivydev64)2022最新可用
    【C++11】shared_ptr智能指针使用详解
    [附源码]java毕业设计自治小区物业设备维护管理系统
    中间件(三)- Kafka(二)
  • 原文地址:https://blog.csdn.net/qq_74276498/article/details/133896522