const
算是一个比较常用的关键字,这里总结一下它的用法,以备后面复习整理使用。
总的来说,const
可以修饰变量(基本数据类型、指针、引用、对象)、函数(普通函数、成员函数)这两大类。
修饰变量
修饰基本数据类型
- 不允许更改变量的值,如
const int a = 3
,若更改a
的值会报错 - 对比宏来说,
const
可以起到类型检查的作用 - 节省空间
- 提高了程序的效率
注意: const
修饰的变量其实可以通过指针来进行修改:
#include <stdio.h>
int main()
{
volatile const int a = 3;
int *p = (int *)&a;
*p = 5;
printf("%d\n", *p);
printf("%d\n", a);
return 0;
}
如果用g++
来编译,需要加volatile
修饰(该关键字的作用是每次取值都从内存中取)。这就说明C++编译器为常量分配了地址,但是使用时直接用立即数进行了替换。
修饰指针
int a = 1;
int b = 2;
//第一种写法
const int *p1 = &a;
*p1 = 3; //报错
*p1 = &b; //正确
//第二种写法
int const *p2 = &a;
*p2 = 3; //报错
*p2 = &b; //正确
//第三种写法
int *const p3 = &a;
*p3 = 3; //正确
*p3 = &b; //报错
第一种和第二种表达的意思一样,即无法通过指针p1
和p2
改变变量a
的值(但是可以通过a自己改变自己的值)
第三种表达的意思是p3
不允许指向其他的变量(可以理解为const
修饰p3
,导致p3
的内容不允许改变,而p3
的值是a
的地址)
修饰引用
int a = 1;
const int &b = a;
b = 3; //报错
- 常量引用这种做法在C++中经常使用,传入引用可以避免产生大量的临时对象,而为了防止传入的对象被修改,所以加上
const
进行修饰
修饰函数
修饰普通函数
int global_a = 3;
//返回指针
const int* return_pointer()
{
int *a = &global_a;
return a;
}
//返回值
const int return_value()
{
int a = 3;
return a;
}
int main
{
int *p1 = return_pointer(); //出错
const int *p2 = test(); //正确
int value1 = return_value(); //正确
const int value2 = return_value(); //正确
}
当const
关键字放在函数开头时,代表返回值是常量。
如果给以”指针传递”方式的函数返回值加const
修饰,则函数返回值的内容不能被修改,该返回值只能被赋给加const修饰的同类型指针。
但是如果函数的返回值只是值传递,由于函数返回给变量的值是复制的一个临时的变量,所以加const
修饰没有意义。
修饰成员函数
- 将
const
关键字修饰成员函数的返回值产生的作用与修饰普通函数一样。这里就不重复说明了。 class Test { public: void func_const() const { a = 3; //错误,常量成员函数中不能修改数据成员的值 test(); //错误,常量成员函数中不能调用非常量成员函数 } void test() { cout << "hello" << endl; } private: int a; };
将
const
放在函数名末尾这是成员函数特有的做法,如果是普通函数则不行。这样达到的目的就是该函数内不允许修改数据成员并且不能调用非常量成员函数。究其本质其实是将
this
指针声明为const
了,实例化类A
之后,调用test()
函数,其实传入了this
指针作为第一个参数,而该this
指针的类型为const A *const this
,对象调用成员函数的利用的就是this
指针,这也就是为什么常量成员函数中不能调用非常量成员函数(*const this
不能转换成*this
)。比如上面的
test()
函数,调用时传入的this
指针的类型是const A *
,而func_const()
则是传入的this
指针类型则是const A *const
,在func_const()
中调用test()
函数,很明显不能将const A *const
转换成const A *
,所以出错。可以引发函数的重载
class Test { public: //引发函数的重载 void func() {}; void func() const {}; };