第二章 头文件、变量和基本类型(8)——复合类型(引用与指针)

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大神的解释中顿悟。在此表示感谢!

        任何地方如有侵权请立即联系删除。

-----------(我是分割线)-----------









猜你喜欢

转载自blog.csdn.net/qq_33737036/article/details/76565803