基础部分
顶层Const 和 底层Const
前言
一般变量添加const来说,没有太多的纠结点直接是顶层const不能改变,变量的值。顶层const和底层const的区别,更多的指的是指针这类复合类型的变量(如果你想我问复合类型是什么???我就有点忍不住想打死个人。基于其他类型定义的类型:如引用和指针等
)
- 指针添加了const 有两种情况
- 1:指向常量的指针:
它的姿势可能有这些:int const *p;const int *p; // const int和int const 是等价的
不能改变其所指向内容(但是内容可以不为常量,只是代表不能通过解引用符来改变指针指向的内容,抽象点来说就是内容不能通过解引用符来操作)
int num = 1; int const *p = # //底层const //*p = 2; 错误,指向“常量”的指针不能改变所指向内容的值 // num = 2; 正确
- 2:指针常量:
它的姿势:int *const p = &v; //声明时必须初始化,const必须放在指针符号* 后面(T *Const)
指针指向对象的地址是常量不能改变地址,所以是顶层const
- 1:指向常量的指针:
int num = 2;
int *const p = # //顶层const
p = &numA; //错误,p 是 *const
总结:顶层表示指针是个常量,底层表示指针所指向的对象是个常量
顶层和底层的作用
区分有2个作用,拷贝限制 强制类型转换
- 1:拷贝时有限制(底层的不能拷贝给非底层const),如下示例:
int numa = 3;
const int *p = &numa; //p_c为底层const的指针
//int *p_d = numa; //错误,不能将底层const指针赋值给非底层const指针
const int *p_d = p; //正确,可以将底层const指针复制给底层const指针
- 2强制类型转换函数const_cast只能运算底层const,如下示例:
int num_e = 4;
const int *p_e = &num_e;
//*p_e = 5; //错误,不能改变底层const指针指向的内容
int *p_f = const_cast<int *>(p_e); //正确,const_cast可以改变运算对象的底层const。但是使用时一定要知道num_e不是const的类型。
*p_f = 5; //正确,非顶层const指针可以改变指向的内容
cout << num_e; //输出5
补充:effective c++
讲到: 只需要判断const是在 * 的左边还是右边即可。
左边 不可以修改它的值 (左边则是修饰被指物,即被指物是常量),
右边 则是修饰指针,即指针是常量,不可以修改它的指向,可以修改指向对象的 对象值;
左右两边 则被指物和指针都是常量,都不可以修改。
代码示例:
int c = 3;
int a = 2;
int b = 1 ;
//const出现在*左边,则被指物是常量
const int * pi = &a;
*pi = b;//不正确 被指物是常量
pi = &c; //正确
//const 出现在* 右边,则指针是常量
int * const p = &a;
p = &c;//不正确,指针是常量
*p = c;//正确
//const出现在*左右两边,则被指物和指针都是常量
const int * const ptr = &a;
ptr = &c;//不正确,指针是常量
*ptr = c;//不正确,被指物是常量
更多扩展
顶层const作用于对象本身
如下所示:
const int c = 42; //不能改变c的字面值,这里const是顶层
int i = c; //正确:当拷贝c值时忽略顶层const
int *const p = &i; //const顶层,这里是指针的地址值是个顶层,不能给p赋值(不能改变p的地址)
*p = 0; //正确我是改变i的字面值,又没有改变p的地址值。没毛病
- 顶层Const作实参初始化形参时会忽略顶层Const(一个拥有顶层Const的形参无法和普通类型形参区分开来)