所属专栏:C“嘎嘎" 系统学习❤️
>博主首页:初阳785❤️
>代码托管:chuyang785❤️
>感谢大家的支持,您的点赞和关注是对我最大的支持!!!❤️
>博主也会更加的努力,创作出更优质的博文!!❤️
>关注我,关注我,关注我,重要的事情说三遍!!!!!!!!❤️
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实
参则采用该形参的缺省值,否则使用指定的实参。
void Func(int a = 0)
{
cout << a << endl;
}
int main()
{
Func(); // 没有传参时,使用参数的默认值
Func(10); // 传参时,使用指定的实参
return 0;
}
替补成员
,我们有正式成员的时候就不需要替补成员。反之如果我们没有正式成员的时候,这个时候就是我们的替补成员上场了。void Func(int a = 10, int b = 20, int c = 30)
{
cout<<"a = "<
void Func(int a, int b = 10, int c = 20)
{
cout<<"a = "<
必须从右往左依次来给出
,不能间隔着给
。我们来看一下这个段代码:void Func(int a = 100, int b , int c = 20)
{
cout<<"a = "<
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++规定了半缺省参数必须从右往左依次来给出,不能间隔着给
函数声明和定义中同时出现
//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++中定义了,函数的声明和定义中,只要声明定义缺省参数就行。
在C语言中我们的函数名只能取一个,不能重名,也就是说如果我们要进行2个数相加,3个数相加……n+1个数相加,我们就要写上n个函数名,并且这些函数名都是不一样的。这下就有点为难我们了,如果这个n很大呢?那就的靠我们的想象力,和排列组合能力了,并且一点我们需要调用这些函数,我们还要记住这些函数名,显然如果函数不能重名的话,确实可能会给我们带来一些困难。
于是C++为了解决这种不方便的地方就有了函数重载的概念。
函数重载:
是函数的一种特殊情况,C++允许在同一作用域
中声明几个功能类似
的同名函数
,这
些同名函数
的形参列表(参数个数 或 类型 或 类型顺序)不同
,常用来处理实现功能类似数据类型
不同的问题。
预处理、编译、汇编、链接。
【_Z+函数长度 +函数名+类型首字母】
。只要参数不同,修饰出来的名字就不一样
,就支持了重载。返回值不同是不构成重载的
,因为调用时编译器没办取了一个别名
,编译器不会为引用变量开辟内存空共用同一块内存空间。
使用语法:类型& 引用变量名(对象名)= 引用实体;
必须初始化
不能引用其他实体
int * const c = &a
,这样我们就跟清楚的能够理解为什么引用一个实体化就不能引用其他实体了。我们能不能引用一个常量呢?
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;
}
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++是更直观的。
int& Add()
{
int n = 0;
n++;
return n;
}
int main()
{
int ret = Add();
cout << ret << endl;
return 0;
}
虽然输出的是1,那是因为虽然Add栈区被回收了,但是之前使用的时候我们有值已经存放进去了,只是回收空间,而里面值还没有被覆盖
,如果被覆盖了输出的就是一个随机值了。
注意:如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用
引用返回,如果已经还给系统了,则必须使用传值返回。
这里我们会发现,引用和指针在汇编中其实没多大区别。可以说是基本相同的。
引用和指针的不同点:
如果在上述函数前增加inline关键字将其改成内联函数,在编译期间编译器会用函数体替换函数的
调用。
假如你有一个函数,它有10000行,如果我们强行的加上inline,那么在我们的汇编就会讲着10000行全部展开,而如果我们要多次进行使用这个函数,拿如果我们有100次调用这函数,拿我们全部展开是多少行呢?是100*10000行,这个时候我们的可执行程序的大小是不是就变大了啊。
而如果我们不进行只能开,而是直接call这个函数,那么我们每次调用这个函数时候,只需要接收这个函数的地址就行了,每次接收这个地址我们就跳转到这个函数二外创建好的空间,直接进行使用了,而这个我们之展开了100+10000行,这样我们的可执行程序的大小是不是就变小啊。
所以inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建
议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不
是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性
宏优点:
1.增强代码的复用性。
2.提高性能。
缺点:
1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查 。
C++有哪些技术替代宏?
1.常量定义 换用const enum
2.短小函数定义 换用内联函数
int* ptr = NULL;
int* str = 0;
NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:
于是为了区分C++11中引入了一个关键子nullptr;