我所遇见的坑(一)
前言
编程多了,就会遇见坑。这些坑可能有自己的不小心,也有可能第三方工具的不小心。本篇记录自己所遇到的关于const的坑,事情起因源于我拷贝一个函数定义,父类函数没有const修饰,子类有const修饰,当我想new一个对象的时候,始终编译不过去。类似如下代码:
1 | class father |
真正的代码要比这个复杂,实例化是宏来调用的,所以我看了老半天,还是找不到哪里出错了。因为用的codeblock,编译过程中输出的都是英文,没有仔细看。后来看了VS编译,发现有提示哪个虚函数没有实现,这才想到看codeblock编译输出的结果。(这是一个惨痛的教训)
const的作用
为了秉持追根到底的思想,特意去查了查const放在函数后面的作用。当然,既然介绍const,就把它的作用介绍全面。
修饰普通类型变量
1 | const int a = 7; |
这个很容易理解,就是a的值不能被改变。深层次我们调试看下不同编译器内存的结果,首先先看VS编译器。
a的值内存上看到的是8,但是实际打印的时候是7。
下面来看g++编译器:
编译器行为一样,都是内存看到的是8,实际打印的是7。
编译器认为a的值是7,所以千万不要轻易对const变量设法赋值,这会产生意想不到的行为。
如果不想让编译器察觉到上面对const的操作,我们可以在const前面加上volatile关键字。
volatile关键字跟const对应相反,是易变的,容易改变的意思。所以不会被编译器优化,编译器也就不会改变对a变量的操作。
以上引用来自于菜鸟教程
const本身就是不让改变的,遵循这个规范即可。
const 修饰指针变量
总共有三种情况,
- 修饰指针所指向的内容的时候
1 | const int* p = 8; |
可以看出,*p = 10 是错误的语法,但是将p指针重新指向另一块内存是可以的。这种情况,const修饰的是右侧的值是不可改变的。打个比喻,比如 p 是一个小纸条,小纸条上用铅笔写着明天会下雨,你可以更改小纸条的内容,但是明天会下雨这个是不能改变的。(PS:这个比喻莫名有些恐怖的气氛。。。)
- 修饰指针的时候
1
2int a = 8;
int* const p = &a;
理解了第一种情况,第二种情况就容易理解了。还是打个比喻,p 是一个小纸条,小纸条上用圆珠笔写着你明天会迟到,小纸条上的内容没有办法修改,但是你可以明天早点起床,这样你就不会迟到了。(PS:说可以修改小纸条的,请出门左走。毕竟这只是个语法规范,超出这个规范,一概不管)
- 同时修饰内容和指针‘这种情况是第一种和第二种的结合体,理解第一第二种,这种情况自然理解了。还是依旧打个比喻,p 是一个小纸条,纸条上用圆珠笔写着明天会下雨,纸条上的内容没有办法改变,明天会下雨也没有办法改变。
1
2int a = 8;
const int* const p = &a;
const 修饰类成员函数
重头戏来了
1 | class test |
如果不注释 a = 10;编译会报错:
就好比,在 逛街 函数中,你只能看不能买。
如果有个成员函数想修改对象中的某一个成员怎么办?这时我们可以使用 mutable 关键字修饰这个成员,mutable 的意思也是易变的,容易改变的意思,被 mutable 关键字修饰的成员可以处于不断变化中
引用与菜鸟教程
一般情况,我们不会遇到这种需求。真要遇到了,查了查,用一用即可。