为什么C++中常量引用可以绑定非常量的对象、字面值和一般表达式 详解

    在c++语言中,除两种例外情况,其他引用的类型都要和与之绑定的对象严格匹配,如int型的引用只能绑定int型的对象;并且引用不能直接与字面值常量或表达式结果绑定。

    其中一种例外情况是:初始化常量引用时,允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。允许为一个常量引用绑定非常量的对象、字面值,甚至是个一般表达式。例如:


// 以下例子来自《Primer c++ 第五版》
int i = 42;
const int &r1 = i;      // 正确
const int &r2 = 42;     // 正确
const int &r3 = r1 * 2; // 正确

    接下来看一个更复杂的例子,并通过这个例子来讲解为什么常量引用是个例外。

double dval = 3.14;
// int &a = dval;    // 编译错误,因为普通引用的类型要与对象类型一致
const int &b = dval; // 编译正确
    c++的自动类型转换机制中,当用一个double去初始化int时,会舍弃掉小数转换为int。在上面的例子中,编译后的代码实际是这样的:

double dval = 3.14;
const int temp = dval; // 由double生成了一个临时的整形常量
const int &b = temp;   // 让b绑定这个临时量
    代码中的改变当然是由编译器完成的。

    在这种情况下,引用绑定的是一个临时量对象而不是dval本身。临时量对象就是:当编译器需要一个空间来暂存表达式的求值结果时,临时创建的一个未命名的对象。

    显然,c++认为,常量引用可以绑定这个临时量,而普通引用就不能绑定这个临时量。

    因为c++认为,使用普通引用绑定一个对象,就是为了能通过引用对这个对象做改变。如果普通引用绑定的是一个临时量而不是对象本身,那么改变的是临时量而不是希望改变的那个对象,这种改变是无意义的。所以规定普通引用不能绑定到临时量上。

    那么为什么常量引用就可以呢,因为常量是不能改变的。也就是说,不能通过常量引用去改变对象,那么绑定的是临时量还是对象都无所谓了,反正都不能做改变也就不存在改变无意义的情况。

    所以常量引用可以绑定临时量,也就可以绑定非常量的对象、字面值,甚至是一般表达式,并且不用必须类型一致。

    这里的逻辑有点绕,可能多花点时间才能理解。其实不理解也无所谓,死记语法也是正常操作。

你可能感兴趣的:(为什么C++中常量引用可以绑定非常量的对象、字面值和一般表达式 详解)