这个部分涉及到引用的原理性描述还是涉及到需要理解的部分的。
问题出现在当你向一个本来形参是一个引用的函数里面传参数时,你传的并不是一个具体的数值,而是一个表达式,这会出现一个什么样的结果呢?C++ Primer Plus中说大部分编译器会告诉你这是个错误,我验证了一下,还真是个错误,如下图所示:
那这是为啥呢?那是因为一个函数形参最终还是只会接收一个实参而不是表达式,那么这个表达式就会计算出一个中间值,然后形参中的引用就会指向这个中间值,因为中间值是临时性的,用完了就没了,而一个引用不能指向一个稍纵即逝的变量,所以它会报错。
但是,如果在形参列表中加上const使之成为const引用,那就可以正常运行了,如下图所示:
那么为什么在这种情况下就可以了呢?想知道答案必须先知道一个新词,叫lvalue,那什么叫lvalue呢?它是一个能够取得地址的数据对象,在C语言中通常被称为左值,因为它们有个确切的地址。而那些文字常量和表达式则属于非左值。而编译器产生中间值只在下面两个情况下。
1、实参类型就是形参类型,但是它不能作为左值,换句话说它只有一个临时性的地址可供访问。
2、实参类型和形参类型不匹配,但是它能够转换成形参类型。
一个形参是const引用只有在上面两种情况下才会产生中间值,而这个中间值的生命期也只是函数的生存期而已。C++认为非const代表你想去改变值,const代表你想只读值。这是合理的,因为你使用const去修饰形参很显然就是想在函数中只读取实参的值,只是去使用它,而不想做别的。所以在这种情况下即使产生中间值也是合法的,合理的。那么这就可以解释为什么非const引用不能接受表达式实参了,因为生成的中间值是临时性质的,对这个中间值进行更改必然不会影响到真正的实参,而你使用非const引用的很大目的就是去改变实参,这就不符合你的初衷了,所以在上述两种情况下也就会报错了。看下面的例子: