引用(不能作为对象):
起一个另外的名字而已,好比如*文华今天叫小华,明天别人叫他小文,他还是他。
注意上述中的引用应该是指“小文”这个名字符号,而不是指小文其人,故引用不是对象!故不能定义引用的引用!而且引用不能与字面值或某个表达式结果绑定在一起,如下是错误的:int &a=10。(再注意:常量引用可以绑定字面值或一般表达式:const int &a=10正确!)
指针(可作为对象):
指向一个对象的复合类型,好比如指向一个建筑的地址牌号。注意其本身也是一个对象。
指针与引用相比:
指针本身是一个对象,存放某个对象的地址,允许对指针赋值和拷贝,在其生命周期内可先后指向不同的对象;
指针无须定义时一定赋确定的值,可用nullptr,0,NULL(头文件cstdlib)初始化一个空指针。引用必须初始化给具体的对象,并将一直绑定在一起。
总结:没有指向引用的指针,可有对指针的引用!
const限定符:
const int a=24;//const对象必须初始化,正确!
const int b;//错误!
常量引用:
相对普通引用而言,引用绑定到const对象上时,称常量引用,最大的区别是常量引用不能用作修改其绑定的对象。
(严格说,引用不是对象,不存在常量引用一说法,人们常常喜欢用它时,不过方便描述罢)
引用与const:
例1
const int a=24;
const int &b=a;//此时引用和引用对应的对象都是常量!
例2
const int a=24;
const int &b=a;
b=8;//b是对常量a的引用,此举想把a改成8,不行!
int &c=a;//c是非常量引用,想通过c改变a,但a是常量,不行!
例3
int a=24;
const int &b=a;//可以有
const int &c=8;//可以有
const int &d=b*2;//可以有
int &e=b*2;//e是一个非常量引用,不行!
例4
int a=24;
int &b=a;
const int &c=a;
b=8;//可以有
c=8;//错误!
(可见对常量引用仅对自己操作限制而已,对引用的本身是否是一个常量则不加限制!)
指针与const:
例5
const int a=24;
int *p=&a;//错误!
const int *p1=&a;//正确!要说明该指针指向的是常量,不能通过指针改变所指对象。不是说指针是常量!
*p1=8;//显然错误!
int b=8;
p1=&b;//正确!p1作为指向常量的指针,仅限制其本身不能改变所指对象的值,并不限制所指向对象是否常量
例6
int a=24;
int *const p=&a;//p将一直指向a,即p是常量指针!
const int b=8;
const int *const p1=&b;//p1本身是常量指针,而且指向常量对象!
提及int *const p与 const int *p区别,常有人分不清甚至说无区别······看明白了:
int *const p:指针p本身是常量,始终指向同一对象,不能改去指另外一对象!且通过p可以改变所指对象内容!
const int *p:指针p本身不是常量,可以改去指向另外一对象!但是通过p不可以改变所指对象内容!
顶层const和底层const:
指针作为一个对象,可指向另外一个对象,这两个对象是否常量是独立的。
顶层const:指针本身是const。更一般地,当任意一个对象是常量时,可称为顶层const。
底层const:指针所指对象是const。更一般地,指针与引用等复合类型的基本类型部分是常量时,可称为底层const。
int a=24;
int *const p1=&a;//const代表指针是常量,顶层。
const int b=8;//顶层
const int &c=b;//顶层
const int *p2=&b;// const代表指针所指对象是常量,底层。
const int *const p3=p2;//左边是底层const,右边是顶层const。