为啥不能使用右值来初始化左值引用?
Posted
技术标签:
【中文标题】为啥不能使用右值来初始化左值引用?【英文标题】:Why a rvalue cannot be used to initialize a lvalue reference?为什么不能使用右值来初始化左值引用? 【发布时间】:2018-03-16 07:29:29 【问题描述】:const A& a = A()
和 A&& a = A()
我可以,但为什么我不能A& a = A()
?
【问题讨论】:
由于过去的一个可能不幸的决定,我想您可能会将仅出现在模板中的转发引用与右值引用混淆。它们共享相同的&&
语法,但它们是完全不同的东西。问题太模糊了。发布 minimal reproducible example 并包含 A&& a = A()
。
@JiveDadson 这个问题对我来说似乎很明显是关于右值引用,而不是转发引用。我回头看看在编辑之前是否可能不清楚,但不,在最初的版本中也很清楚。
@hvd +1。我很困惑为什么这个问题被认为是模糊的。如果有人认为它含糊不清,你能告诉我为什么和在哪里吗?否则,将其搁置为不清楚但不告诉不清楚的地方是非常令人困惑的。
基本原理是,对临时变量进行突变几乎没有意义,任何这样做的尝试都可能是编程错误,而不是深思熟虑的决定。虽然您有时确实想要改变一个临时值,但它通常是出于与改变左值完全不同的原因(存在右值引用以适应这些情况)。
@n.m.我认为这应该是一个答案。
【参考方案1】:
基本原理是突变一个临时的很少有意义。任何这样做的尝试都可能是一个编程错误,而不是一个深思熟虑的决定。
原型示例如下。假设允许绑定到非常量引用。
void foo(int& x, int& y); // sets x and y
int xx, yy;
foo(xx, yy); // xx and yy are set
// now make a small change...
void foo(long& x, long& y); // upgrade
int xx, yy; // forgot to change here
foo(xx, yy); // silently breaks
虽然有时确实想要改变一个临时值,但它通常是出于与改变左值完全不同的原因。发明了右值引用来适应这些情况。
【讨论】:
我试过你的例子,编译失败并出现错误invalid initialization of non-const reference of type ‘long int&’ from an rvalue of type ‘long int
,我知道这是因为在我做第二个foo(xx, yy);
时创建了一个临时变量。但我不太清楚你对// silently breaks
的意思,你能详细说明一下吗?谢谢!
@Eric 你读过我写的吗? 假设绑定到非常量引用是允许的。.
对不起,我误解了你的意思。现在我明白了,如果允许绑定到非常量引用,foo
的功能将被静默破坏。谢谢!【参考方案2】:
通过“初始化左值引用”,您指的是定义从那时起引用所引用的左值。 因此,左值引用将传播对右值“初始化”的任何访问。 IE。您会尝试访问像左值这样的右值表达式。 不可能在所有情况下都像左值一样访问右值。
这就是为什么。
【讨论】:
我不认为这就是他的意思。这个问题太模糊了。 @JiveDadson 你可能是对的。我的印象是,整个(模糊的)问题只是基于对参考是什么的误解。在我看来,整个“它就是事物和事物本身”的想法并没有得到理解。我觉得虽然问题很模糊,但问题很明确。【参考方案3】:右值是暂时的——它很快就会消失。创建对此类对象的左值引用将导致灾难,因为该引用会很快成为对死对象的悬空引用。
【讨论】:
那么为什么右值引用不会变得悬空呢? @songyuanyao 绑定对prvalue的引用会延长prvalue的临时物化的生命周期以上是关于为啥不能使用右值来初始化左值引用?的主要内容,如果未能解决你的问题,请参考以下文章