一、const的使用范围:
通常我们都知道const用于定义常量,但我们相当于只知道把火药用于制作鞭炮,const最大的魅力是它可以修饰函数的参数、返回值、甚至函数的定一体。const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
1、用const修饰函数的参数:
如果参数作输出用,不论它是什么数据类型,也不论采用“指针传递”还是“引用传递”都不能加const修饰,否则该参数将失去输出功能。const只能修饰输入参数:
- 如果输入参数采用“指针传递”,那么const修饰可以防止意外的改动指针,起到保护的作用。
例如StringCopy函数:
void StringCopy(char *strDestination, const char *strSource);
其中strSource是输入参数,strDestination是输出参数。给strSource加上const修饰后,如果函数体内的语句试图改动strSource的内容,编译器将指出错误。
-
如果输入参数采用“值传递”,由于函数将自动产生临时变量用于复制该参数,该参数无需保护,所以不需要加const的修饰。
-
对于非内部数据类型参数而言,像void Func(A a)这样声明的函数注定效率比较低。因为函数体内将产生A内型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程将消耗时间。故为了提高效率而让参数a的值不改变,函数应这样声明void Func(const A &a)。
2、用const修饰函数的返回值:
3、const成员函数:
如果给以“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const修饰的同类型指针。
例如函数
const char * GetString(void);
如下语句将出现编译错误:
char *str = GetString();
正确的用法是
const char *str = GetString();
任何不会修改数据成员的函数都应该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其它非const成员函数,编译器将指出错误,这无疑会提高程序的健壮性。
以下程序中,类stack的成员函数GetCount仅用于计数,从逻辑上讲GetCount应当为const函数。编译器将指出GetCount函数中的错误。
class Stack
{
public:
void Push(int elem);
int Pop(void);
int GetCount(void) const; // const成员函数
private:
int m_num;
int m_data[100];
};
int Stack::GetCount(void) const
{
++ m_num; // 编译错误,企图修改数据成员m_num
Pop(); // 编译错误,企图调用非const函数
return m_num;
}
const成员函数的声明看起来怪怪的:const关键字只能放在函数声明的尾部,大概是因为其它地方都已经被占用了。