C++中关键字const的使用非常灵活,如果能够恰当的使用const,可以在一定程度上提高程序的安全性和可靠性。
关键字const的使用:
1.定义常量
如:
1 const int PI = 3.1415926;
const常量有数据类型,编译器在编译时会进行类型安全检查。而宏常量没有数据类型,只进行字符的替换,没有类型安全检查,在字符替换时有可能会产生错误(边际效应)。
2.修饰指针
如:
1 const int *p = &a;
声明p为一个指向常量a的指针,p指向的对象不能修改,但他可以指向任何地址的常量。
1 int const *p = &a;
声明p为一个指向常量a的指针,p指向的对象不能修改,但他可以指向任何地址的常量。
1 int * const p = &a;
声明p为一个常量指针,它指向a,p这个指针指向的对象不能修改,但他指向的地址的内容可以修改。
1 const int * const p = &a;
声明p是一个指向常量的常量型指针。
注意:如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向 为常量;如果const位于*的右侧,const就是修饰指针本身,即指针本身为常量。
3.修饰函数
3.1 修饰函数的参数
如:
1 void Func(const A &a);
形参为const A &a,则不能对传递进来的引用对象进行改变,保护了原对象的属性。
1 void Func(const A *a);
形参为const A *a,则不能对传递进来的指针的内容进行改变,保护了原指针所指向的内容。
注意:const修饰参数通常用于参数为指针或引用的情况,且只能修饰输入参数;若输入参数采用“值传递”方式,由于函数将自动产生临时变量用于复制该参数,该参数就不需要保护,所以不用const修饰。
3.2 修饰函数的返回值
如:
1 const A *Func();
函数返回的指针指向的对象是一个const对象,它必须赋给一个同样是指向const对象的指针。
1 const A * const Func();
比之前多了一个const,这个const只是在它被用作左值时有效,这个指针除了指向const对象以外,它本身也不能修改,所以就不能当作左值来处理。
注意:一般情况下,函数的返回值为某个对象时,如果将其声明为const时,多用于操作符的重载。通常,不建议使用const修饰函数的返回值类型为某个对象或者对某个对象的引用的情况。如果给采用“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被附给加const修饰的通类型指针。
4.修饰类
4.1 修饰类的数据成员
如:
1 class A 2 { 3 const int maxsize; 4 ... 5 };
const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。所以不能在类声明中初始化const数据成员,因为类的对象未被创建时,编译器不知道const数据成员的值是什么。const数据成员的初始化只能在类的构造函数的初始化表中进行。要想建立整个类中都恒定的常量,应该用类中的枚举常量来实现。
如:
1 class A 2 { 3 enum {maxsize = 100}; 4 ...... 5 };
枚举常量不会占用对象的存储空间,他们在编译时被全部求值。但是枚举常量的隐含数据类型是整数,其最大值有限,且不能表示浮点数。
4.2 修饰类的成员函数
如:
1 void Func() const;
任何不会修改数据成员的函数都因该声明为const类型。如果在编写const成员函数时,修改了数据成员,或者调用了其他非const成员函数,编译器将会报错。
注意:类的构造函数和析构函数都不能是const函数。