目录
1、C++入门
1)C++关键字
2)命名空间
3)C++中的输入输出
4)缺省参数
5)函数重载
6)引用
引用和指针的不同点:
7)auto关键字
8)内联函数
9)指针空值nullptr
1、C++入门
主要介绍C++中新增的一些C语言中没有的内容作为C语言的补充,以便于更加方便地进行编程实现,以及为后期的C++的学习打下基础
1)C++关键字
C++中有98个关键字,而其中32个是C语言中的,我认为对于这些关键字不需要特别地去进行记忆,只需要先做些大概的了解,在后续学习和使用的过程中去逐步地加深理解。
2)命名空间
由于在C语言中时常会出现命名冲突的问题,比如变量名和库冲突、变量名之间的冲突,这会带来很多的不便,于是在C++中就进行了一些优化,使用namespace的关键字,也就是命名空间来设定一个域,实现变量之间的隔离,以此解决冲突问题。几种常见的域:类域、命名空间域、局部域、全局域
//命名空间的定义
namespace A //A为命名空间的名称
{int a; //命名空间中可以定义变量int add(int x,int y) //命名空间中也可以定义函数{return x+y;}
}int a=0; //这是一个全局变量//命名空间可以进行嵌套使用
namespace A
{int a=1; namespace B{int a=2;}
}
如果有多个相同名称的命名空间会被编译器合并,一个命名空间就定义了一个新的作用域,命名空间中所有内容都局限于该命名空间中。在使用时,可以通过作用域限定符来进行访问命名空间中的部分成员,也可以使用using来进行展开命名空间中的内容进行使用,还可以通过using namespace来展开整个命名空间域,此时命名空间中的所有成员都可以被使用
namespace A
{int a=1;
}using A::a; //使用using来展开命名空间中需要的成员,展开的内容就成为了全局域using namespace A; //使用using namespace来展开命名空间域,可以访问命名空间内的所有内容int main()
{A::a=10; //使用作用域限定符来进行使用命名空间中的成员printf("%d",A::a);
}
3)C++中的输入输出
<<为C++中的流插入运算符,可以实现输出
>>为C++中的流提取运算符,可以实现输入
#include<iostream>
using namespace std;
int main()
{int x = 0;int i = 0;int j = 0;cin >> j; //输入cin >> x>>i; //可以连续输入,输入值将按照顺序从左向右放在相应的变量中cout << j << endl; //输出,endl为换行cout << "hello world" << endl<<x <<" " << i; //可以连续输出
}
当然由于C++是兼容C语言的,因此在C++中依然可以使用scanf和printf的函数实现输入输出,不过C语言的这两个输入输出函数会对输入输出的内容进行格式限制,即需要使用%d %c等限定类型,而C++中的cout和cin则并没有限制,这也方便了后期自定义类型的使用。
4)缺省参数
缺省参数使用在函数声明或定义时,为函数的参数设定的一个默认值,当调用函数而未传入参数时就会使用缺省参数,当传入了参数时,缺省参数将不会被使用,也就是说缺少参数担任了一个备胎的角色
缺省可以是全缺省也可以是半缺省(即部分变量有缺省值,部分没有,但半缺省必须从右往左依次给出缺省值,不可以间隔给出,也不可以给左不给右)
#include<iostream>
using namespace std;
void Print(int x=1 ,int y=2,int z=3) //全缺省
{cout << x << " " << y << " "<<z<<" " << endl;
}
void Print1(int x , int y , int z = 10) //半缺省
{cout << x << " " << y << " " << z << " " << endl;
}/*void Print(int x=1 ,int y,int z)
{cout << x << " " << y << " "<<z<<" " << endl;
}
void Print1(int x , int y=1 , int z)
{cout << x << " " << y << " " << z << " " << endl;
}
这两种缺省方式都是错误的
*/
int main()
{Print(); //全部使用缺省值Print(4); //为给参数的部分使用缺省值Print1(99,0); //使用缺省值Print(10,12,16); //不使用缺省值,使用传入的参数}
注意:缺省参数只能在函数声明时出现,或者函数定义时出现(二者之一均正确),不可以在声明和定义中同时出现
5)函数重载
在C++中的同一作用域中可以声明和定义几个功能类似的同名函数,这些函数的形参列表(参数类型、参数个数、参数顺序)不同,但功能类似且函数名相同,那么就构成函数重载
#include<iosteam>
using namespace std;
//1.参数类型不同
int Add(int left, int right)
{cout << "int Add(int left, int right)" << endl;return left + right;
}double Add(double left, double right)
{cout << "double Add(double left, double right)" <<endl;return left + right;
}//2.参数个数不同
void f()
{cout << "f()" << endl;
}void f(int a)
{cout << "f(int a)" << endl;
}//3.参数类型顺序不同
void f(int a,char b)
{cout << "f(int a, char b)" << endl;
}void f(char b, int a)
{cout << "f(char b, int a)" << endl;
}int main()
{cout << Add(1,2) << endl;cout << Add(1.1, 2.2) << endl;f();f(10);f(10,'a');f('a',10);return 0;
}
如果两个函数名称相同、形参相同但返回值不同,则不构成函数重载
那么为什么重载在C语言中不能实现,而在C++中可以实现呢,这是因为在链接的过程中,C语言是通过函数名来查找函数地址的,因此不允许有同名的函数,而C++查找时并不是单纯通过函数名来查找,而是使用了函数名修饰规则,使用参数来进行修饰,同时返回值并没有被用于修饰规则中
6)引用
C语言中的指针的使用较为复杂且易错,因此C++中采用了一种新的方式,即为引用,引用也就是取别名,引用并没有开辟新的空间来存放变量,而是对已经存在的变量取了一个新的名字,因此引用变量与原变量公用一块内存空间,引用不可以改变指向。
比如:西游记中的猴子,可以叫他悟空,也可以叫他齐天大圣
int main()
{int a = 6;int& b = a;//注意:引用类型必须和引用实体是同种类型的cout << b << endl; //打印出b的值和a的值一样b++;cout << a; //由于a、b使用的是同一块空间,因此++时会同时++}
引用的特性:1、引用在定义时必须初始化 2、一个变量可以有多个引用 3、引用一旦引用一个实体,再不能引用其他实体
#include<iostream>
using namespace std;
int main()
{//一个变量可以有多个引用int a=0;int& b=0;int& c=b;//引用在定义时必须初始化//int& d; 报错//引用一旦引用一个实体,再不能引用其他实体int x=10;c=x;//x的值赋值给c,c依旧是a/b对象别名
}
引用的使用场景:1、作为参数(基本任何场景都可以用引用传参)2、作为返回值(要谨慎,如果函数调用结束后,引用的变量已经被销毁,那么该引用相当于野指针,不可以引用返回,除非是静态变量等不被销毁的情况下才可以使用)
引用和指针的不同点:
1、引用概念上定义一个变量的别名,指针存储一个变量地址
2、引用在定义时必须初始化,指针没有要求
3、引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
4、没有NULL引用,但有NULL指针
5、在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
6、引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
7、有多级指针,但没有多级引用
8、访问实体方式不同,指针需要显式解引用,引用编译器自己处理
9、引用比指针使用起来相对更安全
7)auto关键字
auto会根据表达式的类型自动推导出类型,当类型很长时使用auto会比较方便
#include<iostream>
using namespace std;int main()
{int a=0;int b=a;auto c=a;//根据右边的表达式自动推导c的类型auto d=1+1.11;//根据右边的表达式自动推导d的类型cout << typeid(c).name() << endl;cout << typeid(d).name() << endl;//打印变量的类型
}
注意:auto不能作为函数的参数,也不能直接用来声明
auto可以用于for循环,会比较方便,但是for循环的范围一定要是确定的
#include<iostream>
using namespace std;int main()
{int a[]={1,2,3,4,5,6,7,8,9,10};//适用于数组//范围for 语法糖(访问数组)//依次取数组中数据赋值给e//自动迭代,自动判断结束for(auto e : arr){cout << e << " ";}cout << endl;//修改数据for(auto& e : arr){e *=2;}for(auto e :arr){cout << e << " ";}cout << endl;
}
8)内联函数
在进行函数调用时会有一些消耗,比如建立函数栈帧这些,C语言中可以通过使用宏函数来解决,但是宏函数比较容易出错,因此C++中采用了内联函数来解决问题,在调用的函数返回值之前加上关键字inline,即成为内联函数,内联函数会在函数调用的地方展开,则没有函数调用了,所以内联函数不需要建立栈帧,不复杂,不容易出错,可读性强,可以调试
#include<iostream>
using namespace std;
//内联函数
inline int Add(int x,int y)
{return (x+y)*10;
}int main()
{for(int i=0;i<10000;i++){cout << Add(i,i+1) << endl;}return 0;
}
但是宏函数和内联函数都只适用于短小的频繁调用的函数,如果用于较长的函数则会导致代码膨胀,因此当在编写代码时使用了inline只会作为一种建议,最终运行时将会由编译器决定是否将函数设为内联函数
注意:inline函数不能声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到
9)指针空值nullptr
在C语言中我们通常认为NULL就为空指针,但是NULL其实是一个宏定义,NULL就为0
#include<iostream>
using namespace std;
void f(int)
{cout << "f(int)" << endl;
}void f(int*)
{cout << "f(int*)" << endl;
}int main()
{f(0);f(NULL);
}
因此当我们在运行以上代码时会发现只调用了f(int)函数,由于NULL被当做是0而无法调用f(int*)这一函数,为了解决这一问题,在c++中使用nullptr来表示空指针