const关键字可以修饰很多东西使其变成常量,用以保护被修饰的东西,下面我列出了一些我遇到的使用情况。
const修饰指针的时候,可以按*号分成左右。如果const在*左面,那么就是指针常量(pointer to const),意味着*p这个值不能变,也就是说不能通过这个指针修改它指向的那块地址的值。如果const在*右面,那么就是常量指针(const pointer),这个指针可以通过*x的方式修改地址的值,那时不能通过x=&b的形式修改x中的地址。如下图,指针常量是黄色地址内的值不变,常量指针是蓝色地址内的值不变。
#include <stdio.h> int main() { int a = 10, b = 20; const int *p = &a; const int* t = &a; int* const x = &a; int const *y = &a; *p = 11;//编译错误 *p不能修改 *t = 11;//编译错误 *t不能修改 *x = 11; *y = 11;//编译错误 *y不能修改 p = &b; t = &b; x = &b;//编译错误 x不能修改 y = &b; printf("%d\n", *t); return 0; }
参数指针所指内容为常量不可变
void function(const char* Var);
参数为引用,为了增加效率同时防止修改。修饰引用参数时:
void function(const Class& Var); //引用参数在函数内不可以改变
void function(const TYPE& Var); //引用参数在函数内为常量不可变
const int * fun1() //调用时 const int *pValue = fun2(); string的c_str()就是定义为const char* 为了防止用户改动其中的内容
int* const fun2() //调用时 int * const pValue = fun2();
一般情况下,函数的返回值为某个对象时,如果将其声明为const时,多用于操作符的重载。通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。原因如下:如果返回值为某个对象为const(const A test = A 实例)或某个对象的引用为const(const A& test = A实例) ,则返回值具有const属性,则返回实例只能访问类A中的公有(保护)数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。
const修饰类的成员变量,表示成员常量,不能被修改,同时它只能在初始化列表中赋值。
class A { //… const int nValue; //成员常量不能被修改 //… A(int x): nValue(x) { } ; //只能在初始化列表中赋值 };
const修饰类的成员函数,则该成员函数不能修改类中任何非const成员函数。一般写在函数的最后来修饰。这里的const可以作为类成员函数重载的依据,因为const是修饰的隐形参数this。
class A { void function() const; };
对于const类对象/指针/引用,只能调用类的const成员函数,因此,const修饰成员函数的最重要作用就是限制对于const对象的使用。
a. const成员函数不能修改它所在对象的任何一个数据成员,但是可以访问(可读不可写)。
b. const成员函数不能够访问对象的非const成员函数。
const修饰类对象表示该对象为常量对象,其中的任何成员都不能被修改。对于对象指针和对象引用也是一样。
const修饰的对象,该对象的任何非const成员函数都不能被调用,因为任何非const成员函数会有修改成员变量的企图。
例如:
class AAA { void func1(); void func2() const; }; const AAA aObj; aObj.func1(); //× aObj.func2(); //正确 const AAA* aObj = new AAA(); aObj-> func1(); //× aObj-> func2(); //正确
如果想将常量地址赋值给非常量指针,就会编译错误,提示不能将const type转化成type。使用const_type可以解决这个问题。
#include <stdio.h> int main() { const int a = 10; int *p = const_cast<int *>(&a); *p = 20; int& x = const_cast<int&>(a); int y = const_cast<int&>(a); x = 30; y = 40; printf("*p = %d\n", *p); printf("a = %d\n", a); printf("x = %d\n", x); printf("y = %d\n", y); printf("p = %p\n", p); printf("&a = %p\n", &a); printf("&x = %p\n", &x); printf("&y = %p\n", &y); return 0; }
这段代码的输出很有意思,输出如下:
*p = 30
a = 10
x = 30
y = 40
p = 0xbf817000
&a = 0xbf817000
&x = 0xbf817000
&y = 0xbf817004
两个量的地址一样但是输出的值不一样,const依旧是const不管如何的变化其中的值也不会变。转为指针和引用时地址不变,转为变量时,赋值的时候存在一次类型转换,有一次变量的复制,所以地址是新的。
上面的代码是对内置数据类型做的实验,对class或者struct对象的话,指针和引用是可以改变对象的原始值的。推测是因为第12行代码printf
(
"a = %d\n"
, a);
在编译时a的值直接被替换为了10。