为什么xvalues不能绑定到非const lvalue引用?

问题描述:

以下内容无法编译:

#include <iostream>
using namespace std;

int x = 5;
int && f () { return std::move(x); }
int g(int & y) { return y; }

int main() {
    g(f());
    return 0;
}

我很清楚为什么prvalues(未命名的临时对象)不绑定到非const lvalue引用-修改它们是没有意义的,因为它们很快就会消失.但是为什么xvalues不绑定到非const lvalue引用?

It's clear to me why prvalues (unnamed temporaries) do not bind to non-const lvalue references -- it does not make sense to modify them, as they will soon disappear. Yet why do xvalues not bind to non-const lvalue references?

如果函数返回 int&& ,则引用的对象不能是临时的,否则我们将获得悬挂的引用.因此,根据我的理解,如果返回 int& ,则该引用具有附加保证,可以安全地从中移出.

If a function returns int &&, the referenced object can't be temporary, otherwise we would get a dangling reference. Hence if an int && is returned, that's, in my understanding, a reference with the additional guarantee that it's safe to move from it.

纠正了措辞:值"绑定到引用",反之亦然.

Wording corrected: "Values" bind to "references" and not vice versa.

第二以下编译-除了y现在是左值之外,我没有看到概念上的区别.但是它仍然引用x.我了解根据语言规范,为什么应该编译而上面的代码不应该编译.但是,我不了解其背后的原因.为什么单纯的锯齿会改变图片?

Second edit: The following compiles -- I do not see the conceptual difference, besides y now being an lvalue. Yet it still references x. I understand why this should compile and the above shouldn't, by the language specification. I do not, however, understand the reason behind it. Why does mere aliasing change the picture?

#include <iostream>
using namespace std;

int x = 5;
int && f () { return std::move(x); }
int g(int & y) { return y; }

int main() {
    int && y = f(); // reference!
    g(y); // compiles

    // check that y indeed references x
    y = 7;
    std::cout << x << std::endl; // prints 7, of course
    return 0;
}

第三次修改:简而言之,不允许这样做背后的想法是什么

Third edit: In short, what's the idea behind not allowing

int && f() { ... }
int g (int & y) { ...}
g(f());

还允许

int && f() { ... }
int g (int & y) { ...}
int & k (int && y) { return y; }
g(k(f()));

因为这会造成混乱.

左值引用的全部要点是,它们是非临时对象的别名,这些对象的生命周期已经通过其他方式进行管理.右值引用的介绍—而且至关重要的是 std :: move —专门用于创建引用的新类",其绑定表示引用对象最有可能安全"地移出.

The whole point of non-const lvalue references is that they are aliases for non-temporary objects whose lifetime is already being managed by some other means. The introduction of rvalue references — and, crucially, std::move — was specifically to create a new "class" of references whose binding signifies that the referent is most likely "safe" to move from.

如果这些引用对象也能够绑定到简单的 T& ,那么您将会遇到许多模棱两可的转换错误,而且没人会知道该怎么做.您可以将此类转化的排名降低,但是我仍然认为这仍然非常令人困惑.

If these referents also were able to bind to a simple T&, you'd have a slew of ambiguous conversion errors and nobody would know what to do. You could give such conversions a lower rank, but I feel that this would still be extremely confusing.

因此,您正在向后看.问问自己为什么 xvalues不绑定到非常量左值引用.

As such, you're looking at it backwards. Ask yourself instead why xvalues don't bind to non-const lvalue references.