1. const
对象的链接性
1.1 默认状况
- 默认情况下,
const
对象被设定为内部链接,即仅在文件内有效。 - 当多个文件出现同名的
const
变量时,等同于在不同文件中分别定义了独立的变量。
1.2 实现外部链接的方法
对于
const
变量,**不管是声明还是定义* 都添加extern
关键字。即可实现外部链接性。
1 | //file1.cpp定义并初始化了一个常量,该常量能被其他文件访问 |
2 对const
的引用
对
const
的引用即常量引用。
它对且仅对引用可参与的操作进行了限定。对于引用的对象本身是否是一个常量未作限定。
2.1 const
引用的初始化
一般而言,引用的对象必须与引用类型严格匹配。
1 | int i = 0; |
但是,const
引用是个例外,它允许使用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。
1 | int i = 0; |
2.2 内部机制
对于 1
2double d = 3.14;
const int &rd = d;
之所以可以行得通,是因为编译器把上述代码变为了一下的形式: 1
2const int temp = d;
const int &rd = temp;
可以看出const
引用可以绑定临时变量,这是它的一个重要的不同点。而普通的引用是不可以这么做的,因此: 1
2const int &ra = 3 * (2 + 4);//生成临时变量,可以
const int &rb = fun();//fun()为返回一个int临时变量的函数,可以
3. const
与指针
3.1 指向常量的指针
基本概念
不能通过该指针改变指向的量的值(不管它是不是常量)。 1
2double PI = 3.14;
const double *p = Π//不一定非要指向常量
基本原则
一般而言,指针的类型一定要与指向的对象严格匹配,除了两种例外。第一个就是允许令一个指向常量的指针指向一个非常量对象。
指向常量的指针并不要求其指向的对象一定为常量,但普通指针一定不能指向常量。
可以这么想:所谓“指向常量的指针(或引用)”只不过是自以为是罢了,它们觉得自己指向了一个常量,因而自觉地不去改变对象的之。
——《C++ Primer》
3.2 const
指针
基本概念
指针本身是常量,不能变更自己指向的对象。且必须初始化。 1
2int n = 0;
int * const p = &i;//p不可改变,必须一直指向n
3.3 区分
技巧:
- 以
*
符号为界,看const
在左还是在右。 - 只需从右向左阅读r的定义,离变量名最近的符号对变量的类型有最直接的影响, 并以此来分析。
1 | const int *p = &n;//指向常量的指针 |
4. 顶层const
与底层const
4.1 概念
大多数情况下,这对概念是针对指针而言的。
- 顶层
const
若指针本身为常量(即常指针),则称为顶层const
。
更一般的,顶层const
可以表示任意的对象其本身是常量。
1 | int i = 0; |
- 底层
const
若指针所指的对象为一个常量,则成为底层const
。
注意:指向“常量”的指针不代表它所指向的内容一定是常量,只是代表不能通过解引用符(操作符*)来改变它所指向的内容。如
const
引用为底层const。
1 | const int *p2 = &ci;//允许改变p2的值,这是一个底层const |
4.2 记忆技巧
将
const
考虑成向右结合
如果const
右结合修饰的为类型或者*
,那这个const
就是一个底层const
,即指向常量的指针。(底层比较隐晦,从你看到的对象开始,要再转一道才可以)
如果const
右结合修饰的为标识符,那这个const
就是一个顶层const
,即常指针或普通常量。(顶层比较显眼,你看到对象就是)
4.3 作用
为什么要区分顶层和底层呢?这是因为在拷贝赋值时,const
是顶层还是底层对拷贝是否合法起决定性作用。
有以下规则:
- 顶层
const
对拷贝赋值不起影响。
- 左值若无底层
const
, 则右值有无底层const
都无所谓。 - 左值若有底层
const
, 则右值一定不可有底层const
。
简而言之一句话:变量指针或引用不可指向常量。
举例:
1 | int i = 0; |