顶层const和底层const
顶层const和底层const
定义
顶层const:
指针本身是一个常量
即指针本身不能被修改,但可以修改指针所指向的对象本身。
底层const
指针指向的对象是一个常量
即不能通过指针修改所指向的对象本身,但指针指向却可以被修改
示例
int a = 0;
int *const p1 = &a; //顶层const,书写时const放星号左边。
const ci = 42; //顶层const,不能改变ci的值。
顶层const书写时const放里面。
int a = 0;
const int *p1 = &a; //底层const
const int &r = a; //底层const。注意引用的底层实现也是指针
底层相反,放外面。
或者,还可以说成
- 如果 const 右结合修饰的为 类型 或者 *,那这个 const 就是一个底层 const;
- 如果 const 右结合修饰的为 标识符,那这个 const 就是一个顶层 const。
如果我们希望不仅指针本身指向不可变,指针指向的对象本身也不可变,那我们要用双层const来修饰
const int *const p3 = &a; //既是底层const,又是顶层const
对象拷贝
执行对象的拷贝操作时,顶层const不受影响。但在底层const执行对象的拷贝操作时,拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转化。通常非常量可以转换成常量,反之不行。
int a = 0;
const int *p1 = &a; //底层const
int *p2 = p1; //错误p2不是底层const,而p1是
const int *p2;
p2 = p1; //正确,同是底层const
函数传参
顶层 const 不影响传入函数的对象,一个拥有顶层 const 的形参无法和另一个没有顶层 const 的形参区分开
Record lookup(Phone);
Record lookup(const Phone); //错误,重复声明了Record lookup(Phone)
Record lookup(Phone*);
Record lookup(Phone* const); //错误,该const是顶层,重复声明了Record lookup(Phone* const)
而对底层const,则可以区分
Record lookup(Phone&);
Record lookup(const Phone&); //正确,底层const实现了函数的重载
Record lookup(Phone*);
Record lookup(const Phone*); //正确,底层const实现了函数的重载