C++初阶-C++的讲解1

目录

1.缺省(sheng)参数

2.函数重载

3.引用

3.1引用的概念和定义

3.2引用的特性

3.3引用的使用

3.4const引用

3.5.指针和引用的关系

4.nullptr

5.总结


1.缺省(sheng)参数

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

如:

cpp 复制代码
#include<iostream>
using namespace std;
void Func(int n)
{
	cout << n << endl;
}
void Func1(double n = 4.1)
{
	cout << n << endl;
}
int main()
{
	Func(2);
	Func();
	Func1(2);
	Func1();
	return 0;
}

我们在C语言中如果在有参数的时候不传参就会报错,而在C++中如果我们不在声明或定义中设置缺省值都会导致运行出错,但是如果我们在定义时加个缺省值也不会使Func()报错,如:

cpp 复制代码
#include<iostream>
void Func(int n = 4);
using namespace std;
void Func(int n)
{
	cout << n << endl;
}
void Func1(double n = 4.1)
{
	cout << n << endl;
}
int main()
{
	Func(2);
	Func();
	Func1(2);
	Func1();
	return 0;
}

这样就不会有问题,但是最终结果为什么呢?

我们发现我们不传参也会让函数执行该语句,如果我们在定义时设置缺省值而在声明中不设置缺省值结果会怎么样呢?

但是如果我们把声明和定义放在不同文件中呢?

最终都还是能正常打印结果的,所以我们设置缺省值的时候放在哪里都可以。

(2)全缺省:全部参数都给缺省值,半缺省:部分形参给缺省值。

(3)带缺省参数的函数调用,C++规定必须从左到右依次给实参,不能跳跃给实参。

cpp 复制代码
void Func(int a = 10, int b = 20, int c = 30)
{
	cout << a << ' ' << b << ' ' << c << endl;
}
int main()
{
	Func(1, 2, 3);
	Func(1, 2);
	Func(1);
	Func();
	Func(, 2, 3);
	Func(, , 3);
	return 0;
}

我们发现如果顺序给实参就不会报错,不给实参也不会报错,但是跳跃给实参就会报错,这是规定的,我们不能改变,所以以后使用时要注意了哦!

(4)缺省参数在函数声明和定义中同时出现,规定必须在函数声明给缺省值。

cpp 复制代码
void Func(int n = 0 );
void Func(int n = 1)
{
	cout << n << endl;
}
int main()
{
	Func();
	return 0;
}

运行结果为:

我们如果在给声明和定义的缺省值不同的时候就会报错,这个时候我们要及时调整定义的缺省值了,可以不给,但是必须要在声明中给,因为我们之后要改的时候就好改一些,只是现在我们的代码量不多,之后代码量多了就会知道为啥了,我们都把声明放在头文件中,之后修改直接在里面修改就可以了!(4)中的知识我们可以不遵循,但是建议要遵循!

2.函数重载

C++支持在同一个作用域中出现同名函数,但是要求这些同名函数的形参不同,可以是形参类型不同,也可以是形参个数不同,如:

cpp 复制代码
void Func(int a, int b ,int c)
{
	cout << a << ' ' << b << c << endl;
}
void Func(double a, int b)
{
	cout << a << ' ' << b << endl;
}
void Func()
{
	cout  << endl;
}
void Func(int a, int b)
{
	cout << a << ' ' << b << endl;
}
int main()
{
	Func(1, 2, 3);
	Func(1.1, 2);
	Func();
	Func(1, 2);
	return 0;
}

由于我们没有给' '所以第一行结果我们就没有出现1 2 3

但是如果我们给缺省值呢?

我们的Func()不知道到底是调用哪一个函数,所以会造成报错的问题,所以我们的重名函数建议不要给缺省值,否则很容易造成报错的!至于给缺省值的好处,之后就会知道,现在我们是先简单了解一下。

3.引用

3.1引用的概念和定义

引用是给一个变量取别名,而不是新定义一个变量,也不需要新开辟一块空间,引用的变量和被引用的变量共用同一块空间,如:林冲的别名是豹子头,我们可以叫林冲为豹子头,也可以叫他林冲。引用的写法:int a=0;int& b=a;这个b就是a的别名。其中b的类型还是为int相当于&的前面的变量类型就是引用变量的类型。

3.2引用的特性

(1)引用在定义时必须初始化。我们不能直接int& b;

(2)一个变量可以有多个引用。如:int a=0;int& b=a;int& c=a;

(3)引用一旦引用一个实体就再不能引用其他实体,也就是说引用只能引用一次,比如:

int x=10;int y=0;int& d=y;d=x;

d=x的意思到底是把x的值赋值给d(y)还是给x取别名为d呢?

3.3引用的使用

(1)引用在实践中主要是引用传参和引用做返回值中减少拷贝提高效率和改变引用对象时同事改变被引用对象

这句话很难理解,我一句一句来讲,比如我们常用的交换函数就可以来用引用:

cpp 复制代码
void Swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}

这样我们就不需要进行指针的调用了,因为都是一个地址的数据改变。为什么会有"和"后面的内容呢?因为我们的意思就是如果传的参数分别为x,y那么如果a,b改变,那么x,y的值也改变。而这样也不用进行值的拷贝,相对于之前的指针简单多了!

此外,引用也可以给指针变量取别名,可以给结构体取别名,相当于typedef a b;但是我们的a,b只能为变量类型而不能为变量!

如果我们换一个思路来思考:如果我们要增加或减少栈顶所存的数据,那么我们该如何做?

按照之前的思路,我们先取栈顶元素,比如我们要加10,那么我们就让这个栈顶元素加等10,然后把出栈,然后再把结果入栈。但是这样非常麻烦!我们可以直接STTop(s)+=10;在之前看来是不行的,但是这是C++啊,C++规定:返回值具有常性,就相当于被const修饰了。而返回值是临时对象(之后再讲),就相当于临时对象具有常性。所以我们不能通过返回值来修改,而且我们仅仅是改变的只是返回值的结果却不能真正改变栈顶数据,所以我们需要用引用来了。我们之前在定义这个函数时是用的指针吧,现在我们把这个*改为&不也是一样吗,我们这样改了就可以STTop+=10了,因为就是相当于地址所存储的值发生改变了!

需要注意我们不能在函数除了形参外取别名的,因为这样后面空间回收了,而这个地址已经不存储任何数据了就没有任何作用了,所以我们不能进行取别名的操作。

(2)使用引用代替指针传参可以简化程序,避免复杂的指针,其中,结点的结构只能用指针来写,因为需要指针来进行指针指向的改变,而引用却不能改变!

3.4const引用

(1)可以引用一个const对象,但是必须用const引用。const引用也可以引用普通对象,因为对象的访问的权限在引用过程中可以缩小,但是不能放大。

第一句话我们需要用第二句话来理解,我们知道const意味着不可修改,如果我们取了一个别名就变成可修改了,这样是很危险的!因为二者都是一个东西,权限不能扩大。所谓权限就是说变量能修改就是权限大了,不能修改就是权限小了。所以引出第一句话。

const引用也可以引用普通对象,比如:我今天本来准备吃饭,但是人太多了或者有意外的情况下我不准备吃了。这意味着我今天不吃饭,但是后面还是要吃饭的,这是权限缩小,比如:int a=10; const int& c=a;这样的形式是可以的。但是如果const int a=10; int& b=a;这就涉及到权限扩大,是不可以的。

(2)如果我们传参是用另外一个变量类型来传参或者用表达式来传参的情况下,这会生成一个临时对象,这个临时对象具有常性,不可修改。

所以我们可以:const int& b=a*3;但是不可以int& b=a*3因为这个a*3转化为b会涉及到产生临时对象,而这个临时对象在生成的过程中会产生一个别名来存储这个值,而这个别名也是不可修改的,所以我们在进行运算赋值给一个普通引用时就不可以,要用const引用(常引用)。还有一种情况:double d=10.1;int& b=d;会报错,不是d转化为b报错,是因为类型转换时会产生一个临时对象来存储d的小数点前面部分,而这个值也不可修改,所以我们需要const int& b=d

为什么要进行这样?

cpp 复制代码
void func(int& a)
{
	cout << a << endl;
}
int main()
{
	int a = 10;
	func(a);
	func(10);
	func(3.14);
	func(a * 3);
	return 0;
}

我们不能传参以除变量的任何形式,至于原因之前都解释了,但是如果我们加const引用就可以了:

cpp 复制代码
void func(const int& a)
{
	cout << a << endl;
}
int main()
{
	int a = 10;
	func(a);
	func(10);
	func(3.14);
	func(a * 3);
	return 0;
}

这样会使传参的时候类型更丰富。

3.5.指针和引用的关系

二者都有各自的特点,互相不可替代,功能有重叠性。

(1)语法上引用为一个变量取别名,不开辟新空间,指针是存储一个变量地址,要开辟新空间;

(2)引用在定义时,必须初始化,指针建议初始化,但是语法上不是必须的;

(3)引用在初始化引用一个对象后,就不能再引用其他对象,而指针可以不断地改变指向对象;

(4)引用可以直接访问指向对象,而指针需要结引用才能访问指向对象;

(5)sizeof两个东西的含义不同,引用结果为引用类型大学,但指针始终是地址空间锁占字节数;

(6)指针很容易出现空指针和野指针的问题,引用很少出现问题,引用使用起来相对更安全一些(除非引用对象被销毁)。

建议使用引用,指针也可以用,看情况。

4.nullptr

NULL实际是一个宏,在传统C中包含于stddef.h中,在C++中我们如果用NULL,则会打印出0,因为在C++会转换为0,所以相当于直接打印0了,而在C语言中NULL定义为((void*)0),如果打印的话就会报错,因为无法识别。所以我们用nullptr来代替NULL,以防这两个问题。所以我们之后在使用NULL时把NULL改为nullptr即可。

5.总结

这章内容有点上难度了,但是总体来说理解不是很难,主要掌握引用的用法就可以了,其他的不是太大的问题。喜欢的可以一键三连哦,下次再见!

相关推荐
刚入坑的新人编程几秒前
C++STL——容器-list(含模拟实现,即底层原理)(含迭代器失效问题)(所有你不理解的问题,这里都有解答,最详细)
开发语言·c++·链表·list
乄北城以北乀5 分钟前
muduo库源码分析: TcpConnection
网络·c++·后端·中间件
444A4E7 分钟前
C++继承详解:菱形问题、虚继承原理与组合优先原则
c++
程序猿John10 分钟前
单双线程的理解 和 lua基础语法
开发语言·lua
星空露珠15 分钟前
迷你世界脚本之容器接口:WorldContainer
开发语言·数据结构·数据库·游戏·lua
槐月杰19 分钟前
C语言十大经典数学应用
c语言·开发语言·算法
2401_8352613827 分钟前
多线程(Java)
java·开发语言·jvm
天堂的恶魔94629 分钟前
C++项目 —— 基于多设计模式下的同步&异步日志系统(2)(工厂模式)
开发语言·c++·设计模式
Ethon_王36 分钟前
C++ STL vector容器详解
c++
程序猿chen44 分钟前
“堆积木”式话云原生微服务架构(第一回)
java·开发语言·git·后端·微服务·云原生·java-ee