const
如果想保护某个变量的值,使之保存的数据不被修改,可在定义这个变量的时候,在数据类型前加上 const 关键字进行修饰,语法如下:
const 数据类型 变量名;
例如:
const double PI = 3.14159;
PI = 3.14; // 想降低精度偷工减料?有 const 保护,这是行不通的
const 修饰指针变量的两种形式
int N = 0;
const int* pInt1 = &N; // 第一种形式:常量整型指针
int* const pInt2 = &N; // 第二种形式:整型常量指针
因为 const 关键字位置的不同,导致这两种形式所表达的意义也各不相同。 第一种形式所定义的是一个常量整型指针,而第二种形式定义的是一个整型常量指针。
我们可以以‚*‛为界,把定义语句分割成两个部分:
- 如果 const 在
*
的左边,则表示 const 修饰的是 int, 也就是说不能通过这个指针修改它所指向的 int 类型变量,但指针本身的值是可变的; - 如果 const在
*
的右边,则表示 const 修饰的是指针本身,这意味着这个指针的值不能在定义后被修改,所以在定义的同时必须赋初值,但可以通过这个指针修改它所指向的 int 变量的值。 - 使用 const 修饰指针变量,既可以让无法通过指针修改它所指向的数据,也可以让这个指针本身的值无法修改。我们甚至可以在
*
左右都加上 const,既保护它所指向的数据,也保护指针本身:
const int* const pInt3 = &N;
const
的作用
使用 const 代替#define 定义常变量
比如要定义表示圆周率的 PI 常量,可以采用下面的两种方式:
// 定义宏 PI
#define PI 3.1415926
// 定义常量 PI
const double PI = 3.14159
这两种方式在语法上都是合法的,但是第二种方式要比第一种方式好。这是因为如果使用#define定义宏 PI, PI 会在预编译过程中被替换成具体的数字 3.14159,宏的名称不会出现在程序的符号表(编译器在编译程序过程中所收集、记录和使用的一些程序代码当中的语法符号的类型和特征等相关信息。这些信息一般以表格的形式存储于系统中。如常数表、变量名表、 函数名表等,统称为符号表)中,当我们在调试时可能会遇到一个反复出现的数值,但却不知道它的意义,这会给程序的调试带来一定麻烦。而使用 const 定义常变量,既可以保证 PI 值不被修改,,另外变量名会出现在符号表中,便于调试,同时还可以进行类型检查,借助编译器来减少错误的发生。所以,在需要常量的情况下,优先选择使用 const 定义常变量。
使用const修饰函数参数的输入、输出
因为 const 所修饰的变量的不可修改性,所以常常给函数的传入参数加上 const 修饰,表示这是一个传入参数,只是负责向函数内传入数据,防止它在函数内部被非法修改。相应的,对于负责传出数据的传出参数而言,在函数内部会被修改以传出数据,自然就不能加上 const 修饰。所以,有无 const修饰,可以很好地表示函数参数是传入还是传出。例如:
// 复制字符串函数
char * strcpy (
char * destination,// 目标字符串,会被修改,所以没有 const 修饰
const char * source ); // 源字符串,不会被修改,所以加上 const 修饰
修饰类成员函数
如果某个成员函数并没有修改类内部数据的语义,比如 Rect 类的 GetArea()函数,只是用来得到矩形的面积,它不应该去修改矩形的任何数据。为了让这样的函数只做它该做的事防止它修改类内部的数据,在定义的时候,可以在函数末尾加上 const 修饰:
// 矩形类
class Rect
{
public:
// …
// 获得矩形面积,不应该修改类的数据,所以在末尾加上 const 修饰
int GetArea() const
{
// 试图在 const 修饰的成员函数内修改类的成员变量
// 会导致一个编译错误
m_nW = 10;
return m_nW * m_nH; // 只读访问成员变量
}
// 设置矩形的长和宽,会修改类的数据,所以没有 const 修饰
void SetRect(const int nW,const int nH)
{
m_nW = nW; // 修改成员变量
m_nH = nH;
}
private: // 设置私有访问级别保护数据
int m_nW = 0;
int m_nH = 0;
};
在这段代码中, GetArea()成员函数使用 const 修饰,表示这是对类的一个只读访问。如果试图在 GetArea()函数内部修改这个类的数据,编译器就会产生一个编译错误,这可以帮助我们检查程序代码中的对数据的非法修改,改正程序的错误。
const 关键字除了可以发现 const 修饰的成员函数中对数据的非法修改之外,当在一个 const 修饰的常量对象上调用非 const 修饰的成员函数尝试对常量对象进行修改时,编译器也会发现这样的非法修改,从而给出一个编译错误提示我们进行修改。例如:
// 定义一个 const 修饰的常量对象
const Rect rect;
// 在常量对象上调用非 const 修饰的成员函数是非法的
rect.SetRect(3,4);
// 在常量对象上调用 const 修饰的成员函数是合法的
int n = rect.GetArea();