合理使用const可以:
- 便于编译器优化代码
- 增加使用者的可读性
- 避免意外修改变量
当然也有不利的地方:
- 编写时非常繁琐
const变量的特点:
- 赋值运算被禁止
- 定义须有初始值
const变量定义时必须初始化,若不初始化,变量将永远没有机会拥有状态。
const变量的约束:const变量首先收到赋值约束限制,其次因为要保证赋值约束,还对初始化语句类型进行了约束。const可修饰普通变量、引用变量和指针变量,还可以修饰成员函数。
一、const 普通变量这里的普通变量是相对于指针和引用而言的变量。
- 初始化约束
int i=42;
const int ci=i;//int const ci=i;是等价表达
int j=ci;
ci
是一个const普通变量,初始化语句是否正确,取决于左操作数是否会在将来的语句中潜在修改右操作数(比如说赋值)。显然,普通变量的左操作数在赋值完,与右操作数脱离关系,永远不可能修改其右侧操作数。因此我们说,普通const变量初始化,右侧const属性没有要求。但是,普通变量const会禁止赋值
对于指向类的,需要区分指向不变和指向对象不变两种语义。引用绑定后(初始化)永远不能再次修改,因此,指向不变是恒成立的,我们只有指向常量的引用,而没有是常量的引用;但是指向对象不变则是一种声明,这种声明不能与后续赋值操作冲突,否则被认为是非法的。
const int ci=1024;
const int &r1=ci;
r1
是一个指向常量的引用,因为左操作数正确描述了右操作数的常量属性,所以程序没有任何问题。
const int ci=1024;
int &r1=ci;
r1
是一个普通引用,后续操作将会通过r1
对右操作数进行修改,与右操作数矛盾,编译将失败。
int ci=1024;
int &r1=ci;
r1
是一个普通引用,后续操作将会通过r1
对右操作数进行修改,与右操作数不冲突,编译将成功。
int ci=1024;
const int &r1=ci;
r1
是一个常量引用,后续操作不能对右侧操作数修改,与右侧操作数的属性不冲突,编译将成功。
int i=42;
const int &r2=i;
r2
是一个常量引用,后续操作与右操作数不矛盾,编译将成功。
double pi=3.14;
const int &r2=pi;
r2
是一个常量引用,后续操作与右操作数不矛盾,编译将成功。因为类型不匹配,编译器进行了隐式转换,r2
实际绑定的是临时量对象(临时量)
double pi=3.14;
int &r2=pi;
r2
是一个普通引用,后续的操作将会对临时量进行修改,这不符合程序员的初衷,因此编译器禁止这一行为。
指针也是一个指向类的变量,因此要区分指向不变和指向对象不变。我们用术语顶层(top-level const)表示指向不变属性,用底层(low-level)来表示指向对象不变的属性。指针类型既可以具有顶层属性,也可以具有底层属性;由前面讨论可知,引用类型、普通类型的常量属性都是low-level。
int const *p=statement;
const int *p=statement;
int * const p=statement;
const int * const p=statement;
可以从const和*
的相对关系判断const属性是顶层还是底层的,const在*
的左侧为指向对象不变即low-level属性;const在*的右侧为指向不变即top-level属性,从上往下,上述四个语句分别声明了
- low-level pointer
- top-level pointer
- low-level pointer
- 既是top-level亦是low-level
int i=0;
int * const p1=&i;//top
cosnt int ci=42;//top
const int *p2=&ci;//low
cosnt int * const p3=p2;//top and low
const int &r=ci;//low
给定下列语句,判断是否可行:
i=ci;//none vs top
p2=p3;//low vs top and low
编译器是否允许取决于low属性,与top属性无关。在看看下面语句:
int *p=p3;//none vs top and low: low dismatch,error
p2=p3;//low vs top and low:low match,ok
p2=&i;//low vs temp,left low exist,ok
int &r=ci;//low vs top:low dismatch,error
const int &r2=i;//low and top vs none,left low exist,ok
[1] 这里的普通指的是非指向性对象(指针、引用)。