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

Aqu*_*irl 79 c++ pointers reference

错误的形式:

int &z = 12;
Run Code Online (Sandbox Code Playgroud)

正确形式:

int y;
int &r = y;
Run Code Online (Sandbox Code Playgroud)

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

Bru*_*Adi 121

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

Lvalues命名超出单个表达式的对象.例如obj,*ptr,ptr[index],和++x都是左值.

Rvalues是在他们生活的完整表达结束时蒸发的临时值("以分号"表示).例如1729,x + y,std::string("meow"),和x++都是右值.

address-of运算符要求其"操作数应为左值".如果我们可以获取一个表达式的地址,则表达式是左值,否则它是一个右值.

 &obj; //  valid
 &12;  //invalid
Run Code Online (Sandbox Code Playgroud)

  • “_如果我们可以取一个表达式的地址,该表达式是一个左值,否则它是一个右值。_”如果只有 C++ 是那么简单!(但细微差别在这里并不真正相关)“Rvalues are temporaries”临时什么?对象? (2认同)
  • @curiousguyRvalues 是在它们所在的完整表达式结束时消失的临时变量。为了简单地回答为什么“int & = 12;”是无效的,标准说字符串文字是左值,其他文字是右值。 (2认同)

Naw*_*waz 48

int &z = 12;
Run Code Online (Sandbox Code Playgroud)

在右侧,类型的临时对象int是从积分文字创建的12,但临时不能绑定到非const引用.因此错误.它与:

int &z = int(12); //still same error
Run Code Online (Sandbox Code Playgroud)

为什么要创建一个临时的?因为引用必须引用内存中的对象,并且对于存在的对象,必须首先创建它.由于该对象未命名,因此它是一个临时对象.它没有名字.根据这个解释,第二种情况很好,为什么变得非常清楚.

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

const int &z = 12; //ok
Run Code Online (Sandbox Code Playgroud)

C++ 11和Rvalue参考:

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

int && z = 12; //C+11 only 
Run Code Online (Sandbox Code Playgroud)

请注意,有&&一些内容&.还要注意,const不再需要它,即使z绑定到的对象是由integral-literal创建的临时对象12.

由于C++ 11引入了rvalue-reference,int&现在称为左值引用.


Mic*_*ker 9

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

const int& z = 12;
Run Code Online (Sandbox Code Playgroud)

  • @curiousguy,保持一致,你说过"你必须明白这些是C++规则.它们存在,并且不需要任何理由"(更不用说第一版).我怎么解释你的抱怨不给予你自己的东西是不需要的? (2认同)
  • @MichaelKrelin-hacker:技术上不是,你不能(永远)绑定对值(或编译时常量)的引用,标准对于实际发生的事情是非常明确的:*否则,创建一个临时类型"cv1 T1"并使用非参考拷贝初始化(8.5)的规则从初始化表达式初始化.然后将引用绑定到临时*即,允许语法,但语义不是绑定对常量的引用,而是将其绑定到隐式创建的临时. (2认同)

cur*_*guy 5

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

这些是 C++ 语言的规则:

  • 由文字数 ( 12)组成的表达式是“右值”
  • 这是不允许创建具有右值非const引用:int &ri = 12;是非法的构造
  • 允许创建带有右值的 const 引用:在这种情况下,编译器会创建一个未命名的对象;只要引用本身存在,这个对象就会一直存在。

您必须了解这些是 C++ 规则。他们只是。

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

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