0x01 什么是复合类型?
复合类型是基于其他类型定义的类型,本章将介绍引用和指针两种复合类型。
0x02 引用
C++ 11新标准里新增了一种“右值引用”,主要用于内置类。这里,我们所说的引用,指的是“左值引用”。
1、引用相当于为对象取了另一个名字,通过将声明符写成&d的形式来定义引用类型。其中d是声明的变量名;
2、允许在一条语句中定义多个引用:
int i = 1, i2 = 2; // i和i2都是int
int &r = i, r2 = i2; // r是i的引用,r2是int
int i3 = 1024, &ri = i3; // i3是int,ri是i3的引用
int &r3 = i3, &r4 = i2; // r3是i3的引用,r4是i2的引用
3、当引用被用作初始值时,真正参与初始化的其实是引用对象的值;
4、定义引用时,程序把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用,一旦初始化完成,引用将和它的初始值对象一直绑定在一起,因此无法令引用重新绑定到另一个对象;
5、定义了一个引用后,对其进行的所有操作都是在与之绑定的对象上进行的;
6、引用必须被初始化:
int ival = 1024;
int &refVal = ival; // reVal指向ival,即ival的别名
int &refVal2; // 错误,引用必须被初始化!
refVal = 2; // 相当于把2赋予ival
int i1 = refVal; // 等用于i1 = ival
7、引用本身不是对象,所以不能定义引用的引用:
int &refVal3 = refVal; // 正确。但必须注意!refVal3是绑定到ival上,而不是绑定到refVal!
int i = refVal3; // 正确。相当于i = ival
8、引用的类型必须与之绑定的对象严格匹配;
9、引用只能绑定在对象上,不能与字面值或某个表达式的计算结果绑定:
int &refVal4 = 10; //错误!引用类型的初始值必须是一个对象
double dval = 3.14;
int &refVal5 = dval; //错误!类型不符!
0x03 指针
定义一个指针
定义指针类型的方法是将声明符写成*d的形式,其中d是变量名。如果在一条语句中定义了几个指针变量,每个变量前都必须有符号*
int *ip1, *ip2; //ip1和ip2都是指向int类型对象的指针
double dp, *dp2; //dp是double类型对象,dp2是指向double类型对象的指针
获取对象地址
1、指针存放的是对象的地址,想要获取该地址,必须使用取地址符&
int ival = 1;
int *p = &ival; //p存放了ival的地址(p是指向ival的指针)
2、引用不是对象,没有实际的地址,因此不存在指向引用的指针;
3、指针的类型必须和它所指对象的类型严格匹配:
double dval;
double *pd = &dval; //正确。
double *pd2 = pd; //正确。通过一个指针的值赋值给另一个指针
int *pi = pd; //错误!类型不符!
pi = &dval; //错误!类型不符!
利用指针访问对象
如果指针已经指向了一个对象,则允许使用解引用符*来访问该对象:
int ival = 1;
int *p = &ival;
cout << *p; //输出1
*p = 0;
cout << *p; //输出0
空指针
1、空指针不指向任何对象;
2、假如包含了头文件cstdlib,则可以使用预处理变量NULL来给指针赋空值;
3、在C++ 11的新标准中,最直接的方法是用字面值nullptr来初始化空指针:
int *p1 = 0; //最直观的办法,把p1初始化为字面常量0
int *p2 = NULL; //假设存在#include <cstdlib>
int *p3 = nullptr; //C++ 11提供的新方法
4、建议初始化所有的指针,避免使用未经初始化的指针引发程序崩溃。
指针间的比较操作
1、只要指针拥有一个合法值,就能将它用在条件表达式中。指针值为0,条件值取false,其他的指针值,条件值都是ture;
2、对于两个相同类型的合法指针,允许对它们进行算术比较,比较的结果为布尔类型。
空指针类型
1、void *指针是一类特殊的指针类型,可以存放任意对象的地址:
double d = 3.14;
double *pd = &d;
void *pv = &d; //正确。d可以是任意类型的对象
pv = pd; //正确。pv可以存放任意类型的指针
2、可以将之与其他指针比较,或者作为函数的输入与输出,或者赋值给另一个void*指针;
3、不能直接操作void*指针所指的对象,因为不清楚其所指对象的类型。
0x04 理解复杂的复合声明
指向指针的指针
一般来说,声明符中的修饰符个数没有限制,所以,可以定义指向指针的指针,还能定义指向指针的指针的指针,无限衍生下去= =。。
int ival = 1;
int *pi = &ival; //pi指向一个int类型的对象
int **ppi = pi; //ppi指向一个int类型的指针
cout << ival;
cout << *pi; //输出1
cout << **ppi; //需要对指针的指针进行两次解引用,输出1
指向指针的引用
指针是对象,所以存在指针的引用:
int i = 2;
int *p;
int *&r = p; //r是一个对指针p的引用
r = &i; //r引用了指针p,因此给r赋值相当于给p赋值,p指向了i
*r = 0; //解引用r将得到i,相当于i = 0
-----------(我是分割线)-----------
这里的学习顺序基于《 C++ Primer(第五版)》,虽说这本书是C++神书,但如果没有一定的C语言基础,肯定很难一下子啃下来,特别是原书第一章说编写一个简单的程序,结果各种语句和输入输出流都出现了,最后还来个类简介,实在是有点让新手朦逼。就算有一定的C++基础,中文版的语言也略显拗口。
所以,我建议可以先用谭浩强的C/C++系列高校用书籍来打个基础。先别管网上对谭教授的教材评价如何,至少它能高效地带你入门。直接学习C++不是不可以,但毕竟c语言是一门经典的计算机语言,经久不衰,还衍生出了很多其他的计算机语言。学好C语言能培养出一种理解计算机语言的思维模式,以后学其他语言都可能事半功倍。
我个人的学习方式是“先看懂,后深入,再高效”。在这里会按照我的理解,尽量用简单的语言来解释C++的知识点,至少先看懂并让程序能用再说。如果有错欢迎指正。
文中可能有某些程序段来自pezy大神,自学C++的路上我有很多疑难都是在pezy大神的解释中顿悟。在此表示感谢!
任何地方如有侵权请立即联系删除。
-----------(我是分割线)-----------