C++中const的运用及注意
在我学习C++的过程中,对const的应用不可不说是最容易混乱和最容易出错的。但是const却是一个好东西,每一个C++程序员都必须掌握它。以下为本人的一点总结。
1、用const 修饰函数的参数
如果参数作输出用,不论它是什么数据类型,也不论它采用“指针传递”还是“引用传递”,都不能加const 修饰,否则该参数将失去输出功能。const 只能修饰输入参数。
a, 如果输入参数采用“值传递”,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加const 修饰。
b,对于非内部数据类型的输入参数,应该将“值传递”的方式改为“const 引用传递”,目的是提高效率。
例如将void Func(A a) 改为void Func(const A &a)。
c,对于内部数据类型的输入参数,不要将“值传递”的方式改为“const 引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。
例如void Func(int x) 不应该改为void Func(const int &x)。
2、用const 修饰函数的返回值
a, 如果给以“指针传递”方式的函数返回值加 const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。
例如函数
const char * GetString(void);
如下语句将出现编译错误:
char *str = GetString();
正确的用法是
const char *str = GetString();
b, 如果函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加const 修饰没有任何价值。
例如不要把函数int GetInt(void) 写成const int GetInt(void) 。
同理不要把函数A GetA(void) 写成const A GetA(void) ,其中A 为用户自定义的数据类型。
3、 const 成员函数
int Stack::GetCount(void) const
{
++ m_num; // 编译错误,企图修改数据成员 m_num
Pop(); // 编译错误,企图调用非const 函数
return m_num;
}
任何不会修改数据成员的函数都应该声明为const 类型。如果在编写const 成员函数时,不慎修改了数据成员,或者调用了其它非const 成员函数,编译器将指出错误。
4、const 指针
a、将const放在指针变量类型之前。
例如:float f; const float *pf=&f;
表示指针变量指向的数据是一个常量,即不能改变指针指向的数据的值,但可使指针变量指向其他变量。
b、将const 放在*之后,变量名之前。
例如:int i; int *const pi=&i;
表示指针变量的指向不能改变,但可改变指针变量所指向的数据的值。
c、const 一个放在指针变量类型之前,一个放在指针变量名之前。
例如:int i; const int *const pi=&i;
表示指针变量的值,及其所指向的数据都是一个常量,所以都不能改变他们的值。
5、在定义const 对象时必须初始化,因为常量在定义后就不能被修改。例如:const string s="Hello";且默认为文件的局部变量,要使const 变量能够在其他的文件中访问,必须显式地指定它为extern。例如:extern const int i=0;