先简单回忆一下常量的性质:

int main()
{
    const int buffSize = 512;
    buffsize = 512; //× buffSize是常量
}

初始化时:

const int i = get_val();    //√ 运行时初始化
const int j = 42;           //√ 编译时初始化
const int k;                //× k未经初始化

当用一个对象去初始化另外一个对象,他们是不是const就无关紧要

int i = 42;
const int ci = i;
int j = ci;

ci是整形常量,但ci的常量特征仅仅在执行 改变ci 的操作时才会发挥作用

const和引用#

对常量的引用#

把引用绑定到const对象上,称之为对常量的引用

对常量的引用不能用作修改它所绑定的对象,引用 及其 引用的对象 都是常量

const int ci = 1024;
const int &r1 = ci;

需要注意的是:

const int ci = 1024;
const int &r1 = ci;
r1 = 42;        //× r1是对常量的引用
int &r2 = ci;   //× r2是一个非常量引用,ci是一个常量对象

因为不允许把ci用作修改它所绑定的对象,所以也不能通过引用去改变ci(假设第四句合法,那我们就可以通过r2去改变ci了,显然是不对的)

以下两句同理

int &r3 = r1;       //×
const int &r4 = r1; //√

我们口头所说的常量引用其实是对const的引用,严格来说是不存在常量引用的,因为和指针不一样,引用不是对象,我们没有办法让引用本身很定不变

(P.S:由于C++不允许随意改变引用所绑定的对象,所以也可以理解为,所有的引用都是常量,当然了,引用的对象是否是常量,会决定其所能参与的操作,但无论如何也不会影响到引用和对象的绑定关系)

初始化对常量的引用#

我们知道引用的类型必须要和所引用的对象类型一致,但涉及初始化常量的引用会出现第二种例外(第一种:初始化常量引用是允许用任意表达式作为初始值,只要该表达式能转换成引用的类型)

int i = 42;
const int &r1 = i;      //√ 允许const int绑定到一个普通int对象上
const int &r2 = 42;     //√ r2是一个常量引用
const int &r3 = r1 * 2; //√ r3是一个常量引用
int &r4 = r1 * 2;       //× r4是一个普通的非常量引用

为什么会出现这种情况?先来看一个简单的例子

double dval = 0.114514;
const int &ri = dval;
cout < < "ri = " << ri <

运行输出
ri=0
在这个过程中,其实是编译器把代码改成了:

double dval = 0.114514;
const int temp = dval;
const int &ri = temp;
cout < < "ri = " << ri <

这种情况下,ri绑定了一个临时量对象,这下你可看懂上面的代码发生了什么了吧

你可以想象以下,如果ri不是常量时,执行了上述初始化过程会带来怎样的后果:如果ri不是常量。就允许对ri赋值,这样就会改变ri所引用对象的值(此时绑定的是临时量而非dval),所以C++也把以下这种行为归为非法

double dval = 0.114514;
int &ri = dval;     //×
cout < < "ri = " << ri <

同时注意,对const的引用可能引用一个并非const的对象

对const的引用仅对引用可参与的操作做出了限定,对于引用对象本身是否是一个常量没有做出限定,因此对象也可能是个非常量,允许通过其他途径改变它的值

int i = 42;
int &r1 = i;
const int &r2 = i;
//r2 = 0; //× r2是一个常量引用
cout < < "r2 = " << r2 <原文来自:https://www.linuxidc.com/Linux/2019-09/160781.htm

本文地址:https://www.linuxprobe.com/c-const-buffsize.html编辑:public,审核员:张文祥

Linux命令大全:https://www.linuxcool.com/

Linux系统大全:https://www.linuxdown.com/

红帽认证RHCE考试心得:https://www.rhce.net/