C++ 错误:从“int”类型的右值初始化“int&”类型的非常量引用无效

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8293426/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:19:28  来源:igfitidea点击:

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

c++pointersreference

提问by Aquarius_Girl

Wrong form:

错误的形式:

int &z = 12;

Correct form:

正确的形式:

int y;
int &r = y;

Question:
Why is the first code wrong? What is the "meaning" of the error in the title?

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

回答by BruceAdi

C++03 3.10/1 says: "Every expression is either an lvalue or an rvalue." It's important to remember that lvalueness versus rvalueness is a property of expressions, not of objects.

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

Lvalues name objects that persist beyond a single expression. For example, obj, *ptr, ptr[index], and ++xare all lvalues.

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

Rvalues are temporaries that evaporate at the end of the full-expression in which they live ("at the semicolon"). For example, 1729, x + y, std::string("meow"), and x++are all rvalues.

右值是在它们所在的完整表达式的末尾(“在分号处”)消失的临时变量。例如,1729x + ystd::string("meow")x++都是右值。

The address-of operator requires that its "operand shall be an lvalue". if we could take the address of one expression, the expression is an lvalue, otherwise it's an rvalue.

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

 &obj; //  valid
 &12;  //invalid

回答by Nawaz

int &z = 12;

On the right hand side, a temporary object of type intis created from the integral literal 12, but the temporary cannot be bound to non-const reference. Hence the error. It is same as:

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

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

Why a temporary gets created? Because a reference has to refer to an object in the memory, and for an object to exist, it has to be created first. Since the object is unnamed, it is a temporaryobject. It has no name. From this explanation, it became pretty much clear why the second case is fine.

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

A temporary object can be bound to const reference, which means, you can do this:

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

const int &z = 12; //ok


C++11 and Rvalue Reference:

C++11 和右值参考:

For the sake of the completeness, I would like to add that C++11 has introduced rvalue-reference, which can bind to temporary object. So in C++11, you can write this:

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

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

Note that there is &&intead of &. Also note that constis not needed anymore, even though the object which zbinds to is a temporaryobject created out of integral-literal 12.

请注意,有&&intead of &。另请注意,const不再需要它,即使z绑定到的对象是从 integer-literal 创建的临时对象12

Since C++11 has introduced rvalue-reference, int&is now henceforth called lvalue-reference.

由于 C++11 引入了rvalue-referenceint&因此现在称为lvalue-reference

回答by Michael Krelin - hacker

12is a compile-time constant which can not be changed unlike the data referenced by int&. What you cando is

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

const int& z = 12;

回答by curiousguy

Non-const and const reference binding follow different rules

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

These are the rules of the C++ language:

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

  • an expression consisting of a literal number (12) is a "rvalue"
  • it is not permitted to create a non-const reference with a rvalue: int &ri = 12;is ill-formed
  • it is permitted to create a const reference with a rvalue: in this case, an unnamed object is created by the compiler; this object will persist as long as the reference itself exist.
  • 由文字数 ( 12)组成的表达式是“右值”
  • 这是不允许创建具有右值非const引用:int &ri = 12;是非法的构造
  • 允许创建带有右值的 const 引用:在这种情况下,编译器会创建一个未命名的对象;只要引用本身存在,这个对象就会一直存在。

You have to understand that these are C++ rules. They just are.

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

It is easy to invent a different language, say C++', with slightly different rules. In C++', it would be permitted to create a non-const reference with a rvalue. There is nothing inconsistent or impossible here.

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

But it would allow some risky code where the programmer might not get what he intended, and C++ designers rightly decided to avoid that risk.

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

回答by Basile Starynkevitch

References are "hidden pointers" (non-null) to things which can change (lvalues). You cannot define them to a constant. It should be a "variable" thing.

引用是指向可以改变的事物(左值)的“隐藏指针”(非空)。您不能将它们定义为常量。它应该是一个“可变”的东西。

EDIT::

编辑::

I am thinking of

我在想

int &x = y;

as almost equivalent of

几乎相当于

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

where __pxis a fresh name, and the #define xworks only inside the block containing the declaration of xreference.

where__px是一个新名称,并且#define x仅在包含x引用声明的块内起作用。