**【写在前面】**基础语言的复习需要在短时间内迅速完成,对C++语言有了解的人可以简单复习,本篇基础篇会慢慢更新。先更新我认为一些比较重要的规则和一些容易错误的知识点。C++语言颗粒密度很细,想要一次性全部记忆很难,我们先对基础的语言有个了解,后续可以根据这个提纲再看C++ Primer!
一 变量和基本类型
1.1 基本内置类型
1.2 变量
1.3 复合类型
1.4 const限定符
const 对象必须初始化,一旦创建就不能再改变值。在默认情况下,const 对象仅在文件内有效。
如果想在多个文件间共享 const 对象,必须在变量的定义前添加 extern 关键字并在本文件中声明。声明和定义都要加 extern。
1const的引用
C++引入了引用的概念,引用是对对象的取得别名,所以引用在定义的同时需要立刻绑定对象,也就是说引用需要在定义的时候初始化,并且只能使用新建的对象进行初始化。比如
int i=1; int &r = i;//正确
int &r1 = 5; //错误 非常量引用在使用的时候必须用对象进行初始化,而5 是一个常量
const int &r2 = 5;//正确 常量引用初始化可以使用常量
> 【注意 常量引用的和编译器相关,一般情况下右值也必须为常量,但是vs2013发现不必要】
常量引用的时候不可以通过引用去修改 修改右值的时候左值常量引用不会发生任何改变,因为其绑定的是常量的对象。可看例子如下:
2const和指针
const和指针主要分为指针常量和常量指针
指针常量:是一个常量,表示指针所指向的对象是一个常量,指针指向的值不能够修改,但是可以修改指针的指向,这个也叫做底层const。引用都是底层const,不存在顶层const。常量指针:是一个指针,表示指针的指向不能够改变,也就是说不能通过指针变量去改变指针指向的变量的值,但是指针指向的变量的值可以通过其他方式改变。这个叫做顶层const。
int i1 = 5;
int * const p1 = &i1;//常量指针:指针的指向不可以改变,但是可以直接改变i1的值
cout << *p1 << endl << i1 << endl;
i1 = 4;
cout << *p1 << endl << i1 << endl;
int j = 10;
const int * p2 = &j;//指针常量: 指针所指向的值是常量,不可以通过*p2 修改右值
cout << j << endl << *p2;
p2 = &i1;
cout << endl << *p2;
3顶层const和底层const
顶层 const 表示指针本身是个常量(常量指针),底层 const 表示指针所指的对象是一个常量(指针常量)。
顶层const:指针本身是个常量 //可以表示任意的对象是常量,对任何数据类型都适用
底层 const 只用于引用和指针。
顶层 const 的指针表示该指针是 const 对象,因此必须初始化。底层 const 的指针则不用。
实际上只有指针类型既可以是顶层 const 也可以是底层 const,因为引用实际上只能是底层 const,常量引用即为底层 const,不存在顶层 const 的引用。
为啥非要区分顶层const和底层const呢,根据C++primer的解释,区分后有两个作用。
1 执行对象拷贝时有限制,常量的底层const不能赋值给非常量的底层const。也就是说,你只要能正确区分顶层const和底层const,你就能避免这样的赋值错误。如:
int num_c = 3;
const int *p_c = &num_c; //p_c为底层const的指针
//int *p_d = p_c; //错误,不能将底层const指针赋值给非底层const指针
const int *p_d = p_c; //正确,可以将底层const指针复制给底层const指针
2 使用命名的强制类型转换函数const_cast时,需要能够分辨底层const和顶层const,因为const_cast只能改变运算对象的底层const。如:
int num_e = 4;
const int *p_e = &num_e;
//*p_e = 5; //错误,不能改变底层const指针指向的内容
int *p_f = const_cast<int *>(p_e); //正确,const_cast可以改变运算对象的底层const。但是使用时一定要知道num_e不是const的类型。
*p_f = 5; //正确,非顶层const指针可以改变指向的内容
cout << num_e; //输出5
4constexpr和常量表达式
constexpr 是常量表达式,常量表达式在编译阶段就可以确切的知道其值
const int a = 32; // 是常量表达式
const int b = a + 1; // 是常量表达式
const int sz = get_size(); // 不是常量表达式,因为虽然 sz 是常量,但它的具体值等到运行时才知道。
5区分const和constexpr
1.5 处理类型
1类型别名的定义方式
typedef double w1;//定义double 类型为w1
w1 i =19.00; //i 为double类型
using wages = double; // 使用 using 关键字进行别名声明
2 auto类型
auto类型可以表示任意数据类型,尤其是我们学到迭代器的时候,经常使用auto iter = v.begin;
3 decltype
decltype可以直接求解出对应的数据类型
double f =13.2;
decltype(f) h = f;
注意当获得的类型是引用时,必须初始化。
const int ci = 0, &cj = ci;
decltype(ci) x = 0; // x 的类型是 const int
decltype(cj) y = x; // y 的类型是 const int&
decltype(cj) z; // z 是一个引用,必须初始化!!!
引用从来都是作为对象的别名出现,只有在 decltype 处是例外。
decltype 和引用
如果 decltype 使用的表达式不是一个变量,则 decltype 返回表达式结果对应的类型。可以使用这种方式来保证不获取引用类型。
注意解引用指针的结果是一个引用类型。给变量加括号的结果也是引用类型。赋值操作的结果也是引用类型。
int i = 42, &r = i, *p;
decltype(r+0) b; // b 的类型是 int,因为 r+0 的结果类型是 int。
*decltype(p) c = i; // c 的类型是 int&。
decltype((i)) d = i; // d 的类型是 int&。
1.6 自定义数据结构
最后的小作业
1 指针和引用的区别
2 什么是引用,常量引用和非常量引用,引用是左值还是右值
3 底层const和顶层const
4 左值引用和右值引用
5 常量指针和指针常量
6 delctype的用法以及注意事项
7 auto的用法
8 定义类型的别名有几种方式,有什么需要注意的点