const名叫常量限定符,用来限定特定变量,以通知编译器该变量是不可修改的。使用const,可以避免在函数中对某些不应修改的变量造成可能的改动。
非const 变量默认为extern,这样就不可以被程序其它文件访问,要想const变量能够被在其他的文件中访问,必须显式地指定它为extern,如extern const int buffSize = 1024;
1.const 引用
const引用是指向const对象的引用,如下例:
const int ival = 1024;
const int &refVal = ival;
而不可以这样:int &refVal2 = ival;可以读取但不能修改refVal的值。
const引用可以初始化为不同类型的对象或者初始化为右值,如字面值常量:
int i = 42;
const int &r = 42;
const int &r2 = r+i;
这样做完全可以,但是如果同样的初始化对于非const引用却是不合法的,导致编译时错误。
也就是:非const引用只能绑定到与该引用同类型的对象,const引用则可以绑定到不同但相关的类型的对象或绑定到右值。
2.指针变量赋值
首先看下面赋值情况:
int b = 500;
const int* a = &b; [1]
int const *a = &b; [2]
int* const a = &b; [3]
const int* const a = &b; [4]
判断该赋值的规则如下:
如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。
因此,[1]和[2]的情况相同,都是指针所指向的内容为常量(const放在变量声明符的位置无关,[1]和[2]是等价的),这种情况下不允许对内容进行更改操作,如不能*a = 3 ;
[3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的;
[4]为指针本身和指向的内容均为常量。
3.类变量赋值
const A* c=new A();
A* e = c;
解析:根据规则,const位于星号的左侧,所以修饰的变量c的值是常量,而A* e = c,即将常量赋值给指针,而声明指针的目的是为了对其指向的内容进行改变,所以不正确。
A* const c = new A();
A* b = c;
解析:根据规则,const位于星号的右侧,所以修饰的变量c的指针是常量,正确。
A f;
const A& e = f;
解析:e定义为const类型,只能访问声明为const的函数(不改变成员变量的函数),而不能访问一般的成员函数。
4.作为参数和返回值的const修饰符
4.1 修饰参数的const
void fun0(const A* a );
void fun1(const A& a);
调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化,如形参为const A* a,则不能对传递进来的指针内容进行改变,保护了原指针所指向的内容;如形参为const A& a,则不能对传递进来的引用对象进行改变,保护了原对象的属性。参数const通常用于参数为指针或引用的情况;
4.2 修饰返回值的const
const A fun2( );
const A* fun3( );
const Rational operator*(const Rational& lhs, const Rational& rhs)
{
return Rational(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
}
返回值用const修饰可以防止允许这样的操作发生:
Rational a,b;
Radional c;
(a*b) = c;
一般用const修饰返回值为对象本身(非引用和指针)的情况多用于二目操作符重载函数并产生新对象的时候。一般情况下,函数的返回值为某个对象时,如果将其声明为const时,多用于操作符的重载。通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。原因是如果返回值为某个对象为const(const A test = A 实例)或某个对象的引用为const(const A& test = A实例) ,则返回值具有const属性,则返回实例只能访问类A中的公有(保护)数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。
5. 类成员函数const的使用
一般放在函数体后,形如:void fun() const;
如果一个成员函数的不会修改该类数据成员,那么最好将其声明为const,因为const成员函数中不允许对该类数据成员进行修改,如果修改,编译器将报错,这大大提高了程序的健壮性。
6. const使用总结
- 要避免最一般的赋值操作错误,如将const变量赋值;
- 在参数中使用const应该使用引用或指针,而不是一般的对象实例;
- const在成员函数中的三种用法(参数、返回值、函数)要很好的使用;
- 不要轻易的将函数的返回值类型定为const;
- 除了重载操作符外一般不要将返回值类型定为对某个对象的const引用;