const关键字的用法非常灵活, 使用const将大大改善程序的健壮性, const 允许指定一个语义约束,编译器会强制实施这个约束, 允许程序员告诉编译器某值是保持不变的, 如果在编程中确实有某个值保持不变,就应该明确使用const, 这样可以获得编译器的帮助。
定义一个常量, 不允许对其进行修改。
同宏定义一样, 很方便地进行参数的调整,可以做到不变则已,一变都变
const int nMax = 100;
const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误.
// 对传入的参数进行类型检查, 不匹配进行提示
void Function(const int nParam) {
}
防止意外的修改,增强程序的健壮性
//在函数体内修改了 nParam, 编译器会报错
void Function(const int nParam) {
nParam = 10; //error!
}
class A {
void Function(int nParam) {} //函数
void Function(int nParam) const {} //重载函数
};
const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是像 #define
一样给出的是立即数,所以const定义的常量在程序运行过程中只有一份拷贝,而 #define
定义的常量在内存中有若干个拷贝。
编译器通常不为const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
char* const pContent;
const char *pContent;
const char* const pContent;
void Function(const char* Var);
void Function(const int& Var); //引用参数在函数内不可变
这样的一个const引用传递和最普通的函数按值传递的效果是一模一样的,他禁止对引用的对象的一切修改,唯一不同的是按值传递会先建立一个对象的副本, 然后传递过去,而它直接传递地址,所以这种传递比按值传递更有效。
class A {
const int nValue; //成员常量不能被修改
A(int x) : nValue(x) { } ; //只能在初始化列表中赋值
};
class A {
void Function() const; //常成员函数, 不能改变对象的成员变量,也不能调用类中任何非const成员函数。
};
对于const类对象/指针/引用,只能调用类的const成员函数,因此const修饰成员函数的最重要作用就是限制对于const对象的使用。
使用 const_cast
进行转换。
用法:const_cast