为啥不能使用右值来初始化左值引用?

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的临时物化的生命周期

以上是关于为啥不能使用右值来初始化左值引用?的主要内容,如果未能解决你的问题,请参考以下文章

左值右值

c ++使用临时对象右值初始化左值引用以及自动推导[重复]

7. C++左值引用和右值引用

移动构造函数及右值左值引用详解

移动构造函数及右值左值引用详解

为啥定义复制构造函数会给我错误:不能将'obj&'类型的非常量左值引用绑定到'obj'类型的右值?