目录
[前言]
C++可以理解为升级版的C语言
一道算法题,用C语言实现可能需要一百来行代码。但是用C++可能只需要几十行。
但这并不能说明C++比C语言简单,C++还是很有难度的。
学C++的基础一定是建立在C语言之上的,也就是各位宝宝一定要先学会C语言再来学习C++。
在正式开启C++的学习之前,我们要明确一些基础知识。给后期深入学习C++打下基础。
C++中独有的,而C语言中不能支持的语法。
而这些语法知识正可以弥补C语言中的缺陷和不足,让代码的实现变得更加的简洁。
让我们先来了解一下这些知识吧~
一、命名空间namespace
C语言中我们了解了局部域和全局域的概念。
而C++中的域分为局部域、全局域、命名空间域、类域。
在实际项目开发的过程中,一般都是多人共同写一个项目,如果这个时候有两个人定义了同样的变量名,该怎么办?
C++中用命名空间解决了这个问题,命名空间的本质就是定义出一个域,
不同的域之间相互独立,所以在不同域中可以定义相同的变量。并且在一个项目的多文件中定义了同名的namespace会默认为同一个namespace(在最终运行时会合并)。
域的最大作用就是隔离,
并且命名空间域和类域不会影响变量的生命周期。
在实际使用命名空间域的时候,要明确,程序首先会读取局部域,然后是全局域。不会主动读取命名空间内的内容。
如果想要访问命名空间则要打开相应的namespace。
注意!命名空间只能定义在全局中,同时支持嵌套定义。
C++的标准库都放在名为std的命名空间中。
代码理解:
#include<iostream>
using namespace std; //(将命名空间中的全部成员展开)
//日常练习代码可以将std全部展开,但是在写项目的时候不要展开
//可以将常用的成员展开,比如cin和cout
//练习:命名空间
namespace yx
{
int a = 6;
int c = 99;
}
using yx::c; //将yx空间中的c展开,事后用c将不需要::(即不需要指明是哪个空间内的)
int b = 5;
int main()
{
int a = 4;
printf("%d \n", a); //打印局部变量的a
printf("%d \n", b); //打印全局变量的b
printf("%d \n", yx::a); //打印命名空间中的a,(要在前面指明是哪个空间内的)
printf("%d \n", c); //打印命名空间中的c
return 0;
}
二、输入、输出
我们知道C语言中的输入输出分别是scanf和printf。
C++中也有自己的输入输出。即输入cin、输出cout。
对比C语言的输入输出,C++的会更加的简便,不需要在确定是什么类型。
cin和cout都在C++的标准库std中,C++标准库的头文件是<iostream>
代码理解:
#include<iostream>
using namespace std;
//练习:输入输出
namespace yx
{
int a = 6;
int c = 99;
}
int main()
{
//cin和cout自动识别类型
int f = 22;
double g = 33.3;
cout << f << endl;
cout << g << endl; //endl相当于换行
cout << yx::c << endl;
int a = 0;
double b = 0;
cin >> a;
cin >> b;
cout << a << endl;
cout << b << endl;
cout << "打印出来的是:" << b << "和" << a << endl;
return 0;
}
补充:
#include<iostream>
using namespace std;
int main()
{
//在IO需求比较高的地方,可以加上下面三行代码,如需要大量输入的竞赛题中
//提高C++IO效率
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
return 0;
}
三、缺省参数
缺省参数是为函数的参数指定一个缺省值。
我们可以理解为一个默认值,当没有参数传过来的时候,函数自动使用这个缺省值。
要注意缺省值在函数声明和定义同时出现的时候,规定必须在函数声明的时定义缺省值。
缺省参数分为全缺省参数和半缺省参数。其中半缺省参数必须从右往左依次缺省不可以跳跃缺省。
代码理解:
#include<iostream>
using namespace std;
//练习:缺省参数
void Func01(int x = 1, int y = 1)//全缺省
{
cout << x << " ";
cout << y << endl;
}
void Func02(int x, int y = 3, int q = 3)//半缺省
{
cout << x << " ";
cout << y << " ";
cout << q << endl;
}
int main()
{
Func01(2, 2);
Func01();
Func02(4, 4, 4);
Func02(4);//半缺省函数中,非缺省参数一定要传值
return 0;
}
四、函数重载
函数重载的意思就是说,两个同名函数,支持它们同时存在,但是形参要不同(可以是类型不同,也可以是个数不同)。
这就使得C++中的函数调用更加的灵活。
代码理解:
#include<iostream>
using namespace std;
//练习:函数重载
int ADD(int x, int y)
{
return x + y;
}
double ADD(double x, double y)
{
return x + y;
}
int main()
{
int ret01 = ADD(2, 2);
cout << ret01 << endl;
double ret02 = ADD(2.2, 2.2);
cout << ret02 << endl;
return 0;
}
五、引用
引用在C++里面是非常非常好用的存在。
引用就是给变量重新定义一个名字。(相当于给它取一个别名)
在C语言中,我们如果想再次使用某个变量,那通常都是取地址找到这个变量的所在位置,但是在C++中不需要这么麻烦,咱直接拿出这个变量的别名就能使用它了。
给大家举个例子:
在C语言中交换a和b,只有传址才能真正实现两个数的交换。但是在C++中,我们把变量a和b取了别名,为别为x和y。如此是不是交换两个数据的代码实现变得更为简便。
引用在使用的过程中需要注意的是,引用在定义时必须要有初始化。
而且引用只是起一个别名的作用,是不同够改变指向的(这也就说明了引用不能替代指针)
引用的好处就在于:引用传参比指针传参更为方便。
代码理解:
#include<iostream>
using namespace std;
//练习:引用
void Swap(int& x, int& y) //在这里,就不用像之前一样传地址了
{
int tmp = x;
x = y;
y = tmp;
}
int main()
{
int a = 0; //引用的变量必须要初始化
int& a1 = a; //一个变量可以有多个引用(别名)
int& a2 = a;
a1++;
a2++;
cout << a << endl;
//①引用传参
int b1 = 55, b2 = 66;
cout <<"交换前: "<< "b1:" << b1 << " " << "b2:" << b2 << " " << endl;
Swap(b1, b2);
cout << "交换后: "<< "b1:" << b1 << " " << "b2:" << b2 << " " << endl;
//②引用传返回值——>可以直接改变返回值
//略……
return 0;
}
唠叨一句,在学校中使用的数据结构的教材书,上面通常都是C和C++结合写出来的。用C++中的引用替代了指针传参,从而简化代码。
const引用
const引用在函数传参中应用的最多。因为它不仅能接收表达式,而且还能接收不同类型的变量,这就让函数的调用变得更加的灵活 。
const的引用对象有三种:
- 普通对象
- const对象
- 临时对象(表达式/不同类型的变量…)
在表达式结果和数值的类型转换中会产生临时对象来储存中间值,这个临时对象呢它具有常性,也就是说不能够被改变(即本身就自带const修饰),如果用int&来保存就相当于了权限被放大,故临时对象只能被const引用来接收。
注意!!const引用中(以及指针),权限可以缩小但是不能够被放大。
代码理解:
#include<iostream>
using namespace std;
//练习:const引用
int main()
{
const int a = 0;
const int& a1 = a; //想引用const变量必须用const引用
int b = 0;
const int& b1 = b; //用const引用将权限变小(即有了限制)
b++; //b++可以;但是b1++不行,因为被限制了
const int& b2 = b * 3; //【const引用可以接收表达式】
double c = 3.3;
const int& c1 = c; //【const引用也可以接收非己类型的变量】
//const引用在函数传参中非常好用
return 0;
}
引用和指针的关系:
可以把引用理解成辅助指针的。
它们各自有各自的特点,互相不可以取代。
引用可以直接访问对象,但是指针需要解引用才能访问指向对象。
引用不能改变对象,但是指针可以不断改变指向对象。
最后指针很容易出现空指针和野指针的问题,但是引用就不会,所以说引用使用起来会相对安全一些。
六、inline
用inline修饰的函数叫做内联函数(inline放在函数返回值的前面)
inline修饰的函数不能让声明和定义分离,因为inline一旦展开就没有地址了,分离后找不到地址就会报错。建议inline修饰的函数直接在.h文件中定义出来
inline的作用是在编译器调用这个函数的地方,直接展开这个函数,从而不需要建立栈帧(函数的实现都要建立栈帧),以此来提高效率。
但是内联函数具体展不展开是由编译器决定的,我们在函数前加一个inline,只是起一个建议的作用。对于编译器来说,短小的函数是会被展开的,类似递归或者代码很长的函数即使有inline也不会进行展开。
如上图,左右两个函数都加了inline,但是左侧(函数的代码短)的展开了,右侧(函数的代码长)的没有展开,用建立栈帧来实现这个函数
注!VS编译器,release版本会展开inline,但是默认情况下debug版本是不展开的,需要另外设置之后,才能展开。
由上述,是不是联想到了C语言中的宏函数?
因为宏的替换机制,在调用的时候也不用建立栈帧,但是由于宏的缺点很多,写起来极容易出错,所以在C++中用inline代替了宏函数
七、nullptr
NULL的实际其实是一个宏,在C语言中,NULL被定义成无类型指针。
但是在C++中NULL被定义成0,且C++中不支持(void*)的强制类型转换。
所以为了能够有一个可以使用的空指针,C++中定义出了nullptr,以此来避免类型转换的问题。
nullptr可以转换成任意其他类型的指针类型。