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
error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’
提问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 ++x
are all lvalues.
左值命名在单个表达式之外持续存在的对象。例如,obj
、*ptr
、ptr[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.
右值是在它们所在的完整表达式的末尾(“在分号处”)消失的临时变量。例如,1729
、x + y
、std::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 int
is 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 const
is not needed anymore, even though the object which z
binds 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-reference,int&
因此现在称为lvalue-reference。
回答by Michael Krelin - hacker
12
is 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 __px
is a fresh name, and the #define x
works only inside the block containing the declaration of x
reference.
where__px
是一个新名称,并且#define x
仅在包含x
引用声明的块内起作用。