1.C++关键字(C++98)
一共有63个关键字,同时也包括了很多从C语言中延续下来的关键字(for/if…)
2.命名空间(关键字:namespace)
使用命名空间的目的:对标识符的名称进行本地化,避免命名冲突或名字污染
- 命名空间的定义
//定义:namespace+名称{命名空间的成员:可以是变量也可以是函数}
namespace Test{
int a=10;
int b = 20;
}
//命名空间可以嵌套
namespace Test1{
int a = 10;
namespace Test2{
int b = 20;
}
}
//同一个工程下可以有多个名称相同的命名空间,最后编译器会将这些命名空间合并
一个命名空间就是定义了一个作用域,命名空间里的成员都局限于该命名空间
- 命名空间的使用
1.加命名空间及作用域限定符
2.使用using将命名空间中成员引入
3.使用using namespace加命名空间名称引入
namespace Test{
int a=10;
int b = 20;
}
namespace Test1{
int c = 30;
namespace Test2{
int d = 40;
}
}
using namespace Test1::Test2; //这里必须指明Test2是Test1中的成员,否则会报错
int main(){
printf("%d ", Test::a);
using Test1::c;
printf("%d ", c);
printf("%d ", d);
return 0;
}
3.C++输入和输出
输入:cin>>
输出:cout<<
使用时必须加上头文件iostream以及标准命名空间std
C++中输入输出更为方便,不需要添加数据格式,如%d %c…
int main(){
printf("%d ", Test::a);
cout << Test::a ;
return 0;
}
4.缺省参数
缺省参数就是声明或定义函数时为函数的参数指定一个默认值,在调用函数时,若没有指定实参则采用该默认值,否则使用指定的实参
分类:全缺省参数/半缺省参数
注意:
1.半缺省参数必须从右往左依次给出,不能间隔给出
2.缺省参数不能在函数声明和定义同时出现
3.缺省值必须是常量或者全局变量
//全缺省参数
int ADD(int a = 1, int b = 1){
return a + b;
}
//半缺省参数
int SUB(int a, int b = 1){
return a - b;
}
int main(){
int add = ADD();
cout << add;
return 0;
}
//add = 2
5.函数重载
函数重载是函数的一种特殊情况,C++允许在同一作用域下声明几个功能类似的同名函数,这些函数的形参列表必须不同,与返回值类型是否相同无关,用来处理实现功能类似但数据类型不同的问题
调用原理:编译器在编译时需要推演实参的类型,根据推演出的实参类型选择调用具体类型的函数类型.
int ADD(int a, int b){
return a + b;
}
double ADD(double a, double b){
return a+b;
}
//无参函数与带有单个参数的函数不能同时存在
void function1();
void function2(int a=0);
int main(){
ADD(1, 2); //3
ADD(1.0, 2.0); //3.0
//如果没有合适匹配的函数进行调用,编译器可能会尝试进行参数类型转换,
//如果转换成功,则按照转换的类型进行函数调用
ADD('1','2'); //3
return 0;
}
C语言并不支持函数重载
因为C语言和C++的编译器在对函数进行编译时,对函数名字的修饰方法不同,C语言只是简单的在函数名前加下划线;而C++会将函数的参数也含在最终的名字中,保证了函数名字在底层的全局唯一性,也就可以用来区分重载的(同名)函数,这样才不至于报错
在函数前加extern “C” 可以让编译器按C语言的规则来编译该函数
6.引用
引用就是给已经存在的变量取了一个别名,它和它引用的变量共用同一块内存空间
引用的方式:类型& 引用变量名(对象名)=引用实体
引用类型必须和引用的实体同一类型
引用的特性:
- 引用在定义时必须初始化
- 一个变量可以有多个引用
- 引用不可以同时引用多个实体
int main(){
int a = 10;
//引用必须在定义时初始化
int& ra = a;
//一个变量可以有多个引用
int& rra = a;
//引用一旦引用了一个实体,不能再引用其他实体
int b = 20;
//int& ra = b;
ra = 100; //a=100
return 0;
}
使用场景:做参数,做返回值
//做参数
void Swap(int& left, int& right){
int temp = left;
left = right;
right = temp;
}
int main(){
int a = 10;
int b = 20;
Swap(a, b);
return 0;
}
//做返回值
int& ADD(int a, int b){
return a + b; //非常量引用的初始值必须为左值
int ret=(a + b);
return ret;
}
int main(){
int& ret = ADD(1, 2);
ADD(3, 4);
printf("%d", ret); //7
printf("%d", ret); //随机值
return 0;
}
如果函数返回时,离开函数作用域后,其栈上空间已经还给系统,因此不能用栈上的空间作为引用类型返回。如果以引用类型返回,返回值的生命周期必须不受函数的限制(即比函数生命周期长)。
引用和指针的区别:
1.引用必须初始化
2.引用在引用一个实体之后,不能引用其他实体,指针可以随之指向任意一个同种类型的实体
3.没有NULL引用,有NULL指针
4.引用的大小为引用的类型的大小,指针的大小在统一操作系统下是固定的
5.引用自加就是引用的实体增加1,指针自加则指针向后便宜一个类型的大小
6.有多级指针,没有多级引用
7.访问实体方式不同,指针需要显示解引用,引用编译器自己处理
8.引用比指针更加安全(指针需要判空)
7.内联函数
使用关键字inline修饰的函数叫做内联函数,编译时编译器会在调用内联函数的地方展开,没有函数压栈的开销,提升程序的效率
特性:
1.inline是一种以空间换时间的做法,代码很长或者循环/递归的函数不适宜作为内联函数
2.编译器会对inline函数进行优化,如果定义的inline函数体内有循环/递归则会忽略掉内联
3.inline不建议声明和定义分开,因为inline被开就没有函数地址了,链接会找不到,就会导致链接错误
C语言中我们常定义宏的方式来定义一些常量或函数
优点:
1.增强代码的复用性。
2.提高性能。
缺点:
1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查 。
C++替代宏
- 常量定义 换用const
- 函数定义 换用内联函数
8.auto关键字
auto就是把定义变量类型的工作交给编译器来处理,编译器在编译的时候,会根据初始化的表达式来推导变量的实际类型,并将auto替换成实际的类型
使用细则:
1.用auto声明指针类型时,auto和auto*没有任何区别,auto声明引用类型必须加&
2.在同一行定义多个变量时,这些变量必须是相同的类型
3.auto不能作为函数参数,不能直接用来声明数组
4.auto不能定义类的非静态成员变量
5.实例化模板时不能使用auto作为模板参数
int main(){
int a = 10;
auto b = 3.14;
cout << typeid(b).name() << endl;
//auto c = 1, d = 12.34; //auto在同一行初始化,变量的类型必须相同
auto d = 10, e = 20;
auto& ra = a; //auto声明引用类型变量必须加&
auto pa = &a;
auto* pa = &a; //auto声明指针类型变量两种方式都可以
return 0;
}
9.基于范围for循环
对于一个有范围的集合而言,说明循环的范围是多余的,C++11引入了基于范围的for循环
for(范围内用于迭代的变量:被迭代的范围),结合auto关键字使用更为方便
使用条件:
1.for循环迭代的范围必须是确定的
2.迭代的对象要实现++和==的操作
int main(){
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
for (auto& e : array){
e *= 2;
}
for (auto e : array){
cout << e << endl;
}
return 0;
}
10.指针空值nullptr
C++98中用NULL表示指针空值,但NULL实际上是一个宏,可能被定义为字面常量0,或者被定义为无类型指针的常量,在使用的过程中会出错
C++11中使用nullptr代表一个指针空值常量
void fun(int){
cout << "fun(int)"<< endl;
}
void fun(int*){
cout << "fun(int*)"<< endl;
}
int main(){
//fun(0);
//fun(NULL);
fun(nullptr);
return 0;
}