之所以要谈const,大概就是被const出现的各种位置搞得头晕目眩了罢。
(一)C语言中的const关键字
C语言中const修饰的变量或对象的值不能更改。
比如定义const int i = 0;(或int const i = 0;)那么之后任何对i进行改变的操作都会报错。
当然可以投机取巧地去修改const类型的值,比如取得i的指针然后对指针进行操作
const int i = 0; int * p = &i; *p = 3;
const也可以修饰指针类型,这就产生了比较麻烦的情况,那就是判断const修饰的到底是指针还是变量。
判断const修饰谁的方法:先忽略类型名再看const离谁近。
const int *p1; //const修饰*p1,*p1不可变,但是p1可变 int const *p2; //const修饰*p2,*p2不可变,但是p2可变 int * const p3; //const修饰p3,p3不可变,但是*p3可变 const int * const p4; //第一个const修饰*p4,第二个const修饰p4,p4和*p4均不可变
在调试窗口中查看可以发现,p1和p2都是const int*类型,p3是int * const类型,p4是const int * const类型
const修饰符也可以修饰函数的返回值
比如 const int fun(); 返回的就是const int类型,同理const int * fun();返回的是const int *类型
const修饰符也可以修饰函数参数
如果参数用于输出,那么无论是采用指针传递还是引用传递都不能加const修饰,因为const变量不能作为左值
作为输入参数时,如果采用值传递,由于函数将自动产生临时变量复制该参数,所以用不用const没有意义。如果采用指针传递,加const可以防止函数体内部对该参数进行改变。比如C标准库函数strcpy的声明为char *__cdecl strcpy(char *_Dest, const char *_Source),用const修饰源字符串防止对原字符串进行修改。
const也可以外部声明。例如在a1.c中定义int i = 0; 在a2.c中若声明extern const int i;那么i在整个程序中都是const int类型。
(二)C++中的const关键字
在C语言中const修饰的变量是只读变量而不是常量,所以在C语言中即使定义const int n = 10;定义数组int A[n];就会报错,但是在C++中const相当于把一个变量转化成了常量,所以C++中这么写是合法的。所以在C语言中往往是用#define 变量名 变量值来定义一个值替代,但是这样缺乏类型检测机制,在C++中成为可能引发错误,所以在C++里往往用const替代#define。
在C++里const还有个不同于C语言的作用就是在类的成员函数中限定函数类型,成员函数末尾添上const则代表该函数无法改变类的成员变量的值。
class A { public: int n; void fun() const { n++; //报错,修改了成员变量n } };
在C++中const也可以修饰引用型参数,引用相当于给变量起别名,不像值传递那样构造、复制、析构一个临时对象,但是一旦作为参数的引用对象发生了改变,原参数也会发生改变,如果为了避免引用对象被不小心改变,可以用常引用类型即const Type &作为参数。
C与C++的const关键字