引用和指针都属于复合类型(基于其他类型定义的类型)
1、引用
引用为对象起了另外一个名字,引用类型引用另外一种类型。通过声明符写成&d的形式来定义引用类型,其中d是声明的变量名:
int ival = 1024;
int &refval = ival; // refval指向ival(是ival的另一个名字)
int &refval2; // 报错: 引用必须被初始化
一般在初始化变量时,初始值会被拷贝到新建的对象中。然而定义引用时,程序会把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用。一旦初始化完成,引用将和它的初始值对象一直绑定在一起。因为无法令引用重新绑定到另一个对象,因此引用必须初始化。
引用并非对象,相反的,它只是为一个已经存在的对象起的另外一个名字。为引用赋值,实际上是把值赋给了与引用绑定的对象。获取引用的值,实际上是获取了与引用绑定的对象的值。同理,以引用作为初始值,实际上是以与引用绑定的对象作为初始值。因为引用本身不是一个对象,所以不能定义引用的引用。
引用的类型必须与其所引用对象的类型一致:
double dval = 3.14;
int &refval = dval; // 错误:此处引用类型的初始值必须是int型对象
const 的引用
可以把引用绑定到const对象上,就像绑定到其他对象上一样,我们称之为对常量的引用。与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象:
const int ci = 1024;
const int &r1 ci; // 正确:引用及其对应的对象都是常量
r1 = 42; // 错误:r1是对常量的引用
int &r2 = ci; // 错误: 试图让一个非常量引用指向一个常量对象
前面提到:引用的类型必须与其所引用对象的类型一致,但有例外:
double dval = 3.14;
const int &ri = double;
此处ri引用了一个int型函数。对ri的操作应该是整数运算,但dval却是一个双精度浮点数而非整数。因此为了确保ri帮顶一个整数,编译器把上述代码变成如下形式:
const int tmp = dval; // 由双精度浮点数生成一个临时的整型常量
const int &ri = tmp; // 让ri绑定这个临时量
2、指针
指针是指向另一种类型的复合类型。与引用类似,指针也实现了对其他对象的间接访问。然而指针与引用相比又有很多不同点。其一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以指向几个不同的对象。其二,指针无需在定义是赋初值。和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。
定义指针类型的方法将声明符写成*d的形式,其中d是变量名:
int *ip; // 指向int型对象的指针
double *dp; //指向double型对象的指针
在声明语句中指针的类型实际上被用于指定它所指向对象的类型,所以二者必须匹配。如果指针指向了一个其他的对象,对该对象的操作将发生错误:
double dval;
double *pd = &dval;// 正确:初始值是double型对象的地址
double *pd2 = pd;// 正确:初始值是指向double对象的指针
int *pi = pd; // 错误:指针pi的类型与pd的类型不匹配
pi = &dval; // 错误:试图把double型对象的地址赋给int型指针
指针值
指针的值(即地址)应属下列4种状态之一:
1、指向一个对象
2、指向紧邻对象所占空间的下一个位置
3、空指针
4、无效指针
指针和const
与引用一样,也可以令指针指向常量或非常量。类似于常量引用,指向常量的指针不能用于改变其所指对象的值。要想存放常量对象的地址,只能使用指向常量的指针:
const double pi = 3.14;//pi是一个常量,它的值不能改变
double *ptr = π //错误:ptr是一个普通的指针
const double *cptr = π //正确:cptr可以指向一个双精度常量
*cptr = 42; //错误:不能给*cptr赋值
前面提到:指针的类型必须与其所指对象的类型一致,但有例外:
double dval = 3.14; //dval是一个双精度浮点数,它的值可以改变
cptr = &dval; //正确:但是不能通过cptr改变它的值
允许令一个指向常量的指针指向一个非常量的对象。
最后总结一下:所谓的指向常量的指针和引用,不过是指针或引用”自以为是”罢了,它们觉得自己指向了常量,所以自觉地不去改变所指对象的值。
重点:
★相同点:
●都是地址的概念;
指针指向一块内存,它的内容是所指内存的地址;而引用是一个可以指向该内存并且能自动解引用的 也叫作别名
★不同点:
●指针是一个实体,而引用仅是个别名;
●引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;
●引用没有const,指针有const,const的指针不可变;
●引用不能为空指针可以
●“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;
●指针和引用的自增(++)运算意义不一样;
●引用是类型安全的,而指针不是 (引用比指针多了类型检查)
使用时尽量使用引用在传参的时候,毕竟少了一次拷贝构造;
对于类的引用成员变量在初始化列表中初始化: