1.修饰变量
1.1 作用
功能:不能直接被修改
const修饰变量,就相当于是定义了一个常量。该变量不能直接被修改,但是可以通过指针修改。
作用:便于维护、提前发现可能错误的修改
比如程序中大量使用了一个数字10,且不会对其修改,就可以将其定义为const常量,这样若其他地方对其进行了直接修改,编译阶段就会报错;且以后如果要改变这个数字,那么只需要改变定义时这一个地方就可。
1.2 修饰局部变量
(1)C环境下
(2)C++环境下(常量折叠)
在C++环境下,我们运行同上代码:
我们发现通过指针修改后, val还是输出的10,*p输出的是20,两个的地址也是一样的,但输出值不同,这是什么原因?
常量折叠:
这就是C++中的常量折叠:const变量(即常量)值,会被存放到编译器的符号表中,参与计算时直接从符号表中取出数据,省去了内存访问的操作,这就是编译器进行的一种优化。编译器在预处理的时候,就对const变量val进行了替换(只读取了这一次),所以输出的是原先的10,而*p指向的是val的存储空间,也实际改变了val存储的数据,所以输出的是20。
const修饰的局部变量:是存储在栈区中。
解决方法:
使用volatile关键字修饰该变量,保持变量的内存可见性,这样每次访问该变量内容时,都会通过内存去获取。
1.3 const修饰全局变量(C/C++)
上述内容是在局部const变量条件下,若const修饰的是全局变量,再通过指针去修改,则会引发异常,写入访问权限冲突,也就是不可写。
原因:const修饰的全局变量存储在内存的全局区中,其只有可读属性,无法修改。
2.修饰指针
2.1 指针常量
指针常量:const修饰指针变量名
表示指针的指向不能被修改,但是指向的内容可以被修改。
2.2 常量指针
常量指针:const修饰*
表示指针指向的内容不能被修改,但是指针的指向可以修改。
注意:
当然也可以利用两个const分别修饰*和指针变量名,表示该指针的指向和指向的内容都不能被修改。
3.修饰数组
表明数组中的每个元素都是const属性,其特性同上。
4.修饰函数形参
(1)void func(const int val);
形参不能被修改。
(2)void func(const int* val);
指针形参指向的内容不能被修改,因为实参和形参指向的是同一个地址,所以可以防止函数内部通过形参进行修改其指向内容,起到保护实参指向内容的作用。
(3)void func(int* const val);
指针形参的指向不能被修改。
(4)void func(const int& val);(C++)
引用实体无法被修改,保护实体。注意:const放到&符号后不起作用。
注意:const实参不能传递给非const形参;非const实参可以传递给const形参。
5.修饰函数返回值
5.1 修饰普通类型返回值
没有意义,因为返回的本身就是一个临时变量,具有常量性。
5.2 修饰指针类型返回值
(1)const修饰*
不能将权限放大,所以不能赋值给非const属性变量。
(2)const修饰指针变量名(在*后面)
此时可以将其赋值给非const变量,因为此时指针指向的内容可以被修改,将其赋值给非const变量后,也可以对其指向的内容进行修改,并没有放大对指向内容的访问权限。
5.3 修饰引用类型返回值(C++)
同样只能赋值给const类型引用,表示不能对引用实体进行修改。
6.修饰类的成员变量(C++)
const修饰类的成员变量,表示其为成员常量,不能被修改,且只能在初始化列表进行初始化。(注:C++98和11中,也支持了声明时初始化,但还是推荐使用初始化列表进行初始化)
7.修饰类的成员函数(C++)
const修饰的类成员函数称为const成员函数,本质上const修饰的是该成员函数隐藏的this指针,表示在该函数内,不能对类的任何成员进行修改。
this本身的类型:Time* const this
const修饰后:const Time* const this
相当于this本身的指向就是不能被修改的,通过const成员函数的const修饰后,其指向的内容也不能被修改。
相关问题:
(1)const对象能否调用非const成员函数?
不能,const类型对象只能调用const成员函数,不能调用普通成员函数。因为普通成员函数可能会对对象中的成员进行修改。
(2)非const对象能否调用const成员函数?
可以,普通对象对于普通成员函数和const成员函数都可以调用。
(3)const成员函数内,能否调用其他的非const成员函数?
不能,同理非const成员函数可能会对对象的成员进行修改,而const成员函数内不能对对象的任何成员进行修改。
(4)非const成员函数内,能否调用其他的const成员函数?
可以。
注意:
构造函数,拷贝构造函数,析构函数,赋值运算符重载,不可以使用const修饰。因为以上四个函数目的就是对成员进行修改。
mutable关键字:
mutable关键字修饰成员变量,表示该成员变量可以在const修饰中被修改。