顶层const表示指针本身是个常量,底层const表示指针所指的对象是一个常量。
int i=0;
int * const p1=&i; 不能改变p的值,p是一个指针,所以p是一个顶层const
const int * p2=&i; 表示不能改变指针所指i的值,所以是一个底层const
const的顶层和底层不只是限定于指针,进行推广后。
顶层const可以表示任意的对象是常量,这对任意数据类型都适用,如算术类型、类、指针等。
底层const则表示与指针和引用等复合类型的基本类型部分有关。
其中与引用有关的const都是底层const
const int num=0;这就是一个顶层const
auto e=# 这里的e是一个指向整形常量的指针,因为对于对象取地址是一个底层const,所以auto会保留。
其中指针类型比较特殊,它既可以是底层const也可以是顶层const。
cosnt int*const p3=&i; 靠右的const是指指针本身,所以是顶层const;靠左的const是指指针所指向的数据类型,所以是底层
const。
因为引用的值就是其所指对象的值,引用在其生命周期中的值不会进行改变,所以引用的const都是底层const。
int const&a=i;
i和a都不能进行改变。
const int &b=i;
i可以改变,从而改变b的值,因为i本身不是一个常量,只是引用认为他是常量。
所以const的顶层和底层的判断主要是看其const是限定的其对象本身,还是限制其所指的对象。
非const变量不可以赋值给const变量,但是const变量可以赋值给非const变量。
非常量可以将地址赋值给const指针,但是常量不可以将地址赋值给非const指针。
可以将非const对象赋值给const引用。因为引用本身是一个指针,不可以通过引用来修改该对象,但是可以通过其他方法来修改该对象。
int i = 1;
int &r1 = i;
const int &r2 = i;
r1 = 0;// 正确
r2 = 9;// 错误
引用必须初始化,因为引用一旦初始化不能绑定其它对象。