错误:从类型为"int"的右值初始化类型为"int&"的非 const 引用无效

error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’

本文关键字:int 类型 的非 const 无效 引用 初始化 错误      更新时间:2023-10-16

错误的形式:

int &z = 12;

正确形式:

int y;
int &r = y;

问题
为什么第一个代码是错误的?标题中错误的">含义"是什么?

C++03 3.10/1说:"每个表达式要么是左值,要么是右值。"重要的是要记住,左值与右值是表达式的属性,而不是对象的属性。

Lvalues命名持久存在于单个表达式之外的对象。例如,obj*ptrptr[index]++x都是左值。

R值是临时值,在其所在的完整表达式末尾("在分号处"(蒸发。例如,1729x + ystd::string("meow")x++都是右值。

运算符的地址要求其"操作数应为左值"。如果我们可以取一个表达式的地址,那么这个表达式就是一个左值,否则就是一个右值。

 &obj; //  valid
 &12;  //invalid
int &z = 12;

在右侧,类型为int的临时对象是从整型文字12创建的,但该临时对象不能绑定到非常量引用。因此出现了错误。与相同

int &z = int(12); //still same error

为什么要创建临时?因为引用必须引用内存中的对象,而要想使对象存在,必须首先创建它。由于该对象未命名,因此它是一个临时对象。它没有名字。从这一解释中,我们可以很清楚地理解为什么第二种情况是好的。

临时对象可以绑定到const引用,这意味着,您可以这样做:

const int &z = 12; //ok

C++11和Rvalue参考:

为了完整起见,我想补充一点,C++11引入了右值引用,它可以绑定到临时对象。所以在C++11中,你可以这样写:

int && z = 12; //C+11 only 

注意,&的后面有&&。还要注意,const不再需要,即使z绑定到的对象是由整数12创建的临时对象。

由于C++11引入了左值引用,因此int&现在被称为左值引用

12是一个编译时常数,与int&引用的数据不同,它不能更改。可以做的是

const int& z = 12;

非常量和常量引用绑定遵循不同的规则

以下是C++语言的规则:

  • 由文字数字(12(组成的表达式是"右值">
  • 不允许创建具有右值的常量引用:int &ri = 12;格式错误
  • 允许使用右值创建const引用:在这种情况下,编译器创建一个未命名的对象;只要引用本身存在,这个对象就会一直存在

你必须明白这些都是C++规则。他们就是这样。

发明一种不同的语言很容易,比如C++,规则略有不同。在C++中,允许创建带有右值的非常量引用。这里没有不一致或不可能的地方。

但它会允许一些有风险的代码,程序员可能无法得到他想要的,C++设计者正确地决定避免这种风险。

引用是指向可以更改的事物(lvalues(的"隐藏指针"(非null(。不能将它们定义为常量。它应该是一个"可变"的东西。

编辑::

我在考虑

int &x = y;

几乎等同于

int* __px = &y;
#define x (*__px)

其中__px是新名称,而#define x仅在包含x引用声明的块内工作。