【问题标题】:Why is const rvalue reference implicitly converted into const reference?为什么 const rvalue 引用隐式转换为 const 引用?
【发布时间】:2020-07-20 10:30:08
【问题描述】:
#include <iostream>
using namespace std;

class foo {
public:
    foo() {}
    foo(const foo& other) {cout << "foo's copy constructor " << endl;}
    foo(foo&& other) {cout << "foo's move constructor " << endl;}
    foo(const foo&& other) {cout << "foo's move constructor with const ref ref" << endl;}
};

class bar {
public:
    bar(const foo& f) : f_(move(f)) {}
    foo f_;
};

int main()
{
    foo f;
    bar b(f);
}

在上面的代码中,在没有移动构造函数--foo(const foo&& other)的情况下,右值引用move(f)被隐式转换为const引用,因此调用了 foo 的复制构造函数。

我的问题是为什么 const 右值引用隐式转换为 const 引用而不是编译器错误?具体来说,如果我注释掉最后一个移动构造函数,则调用 foo 的复制构造函数。

【问题讨论】:

  • 澄清一下,你是在问为什么问题中的代码没有给出错误?如果您实际上是要询问没有显示其中一个构造函数的代码,请对代码进行编辑。
  • 右值引用仍然是引用,因此它可以绑定到 const 左值引用。但是 const 右值引用没有意义,因为 const 对象不能被移出。
  • @M.M 我的问题是关于从 const ref ref 到 const ref 的隐式转换以及为什么允许它(转换)而不是编译器错误。在我的代码中,如果最后一个移动构造函数被注释掉,则调用 foo 的复制构造函数。由于从 const ref ref 到 const ref 的隐式转换,调用了复制构造函数。我期待一个警告或错误,但不知道这种隐式转换。所以我想知道是否有任何理由允许在 C++ 中进行这种隐式转换。
  • @bigdata2 这里没有隐式转换,引用参数直接绑定到实参

标签: c++


【解决方案1】:

一些具有相同引用绑定的更简单的代码:

int main()
{
    const foo f;
    const foo&  g = std::move(f);
    const foo&& h = std::move(f);
}

表达式std::move(f) 最好描述为const foo 类型的xvalue。

所以我们有一个由const foo 类型的xvalue 初始化的引用。

gh 都是合法的,引用直接绑定。 const foo&amp;&amp; 只能绑定到右值,但const foo&amp; 可以绑定到左值和右值。 (xvalue 是 rvalue)。

没有标题中建议的隐式转换,引用直接绑定到初始化器指定的对象。


在发布的代码中,在我的示例中,两个构造函数之间的重载解析与gh 具有相同的绑定。重载解析选择参数类型const foo&amp;&amp;const foo&amp; 更好地匹配const foo 类型和类别“xvalue”的参数,因为有一个排名规则,如果其他所有条件都相同,右值参数更喜欢右值引用。

但是如果你删除了这两个构造函数中的任何一个,那么另一个将被选中。

【讨论】:

  • 是否有理由允许 const 引用绑定到 xvalues?我理解延长 xvalue 生命周期的原因,如本答案 (stackoverflow.com/questions/34240794/…) 中所建议的那样,但是可以通过将 xvalue 绑定到右值引用来延长生命周期,那么为什么允许将其绑定到 const&?
  • @bigdata2 const 左值引用绑定到右值自第一个 C++ 标准以来一直存在,其基本原理是,如果你不修改它,它是什么类别并不重要
  • 编译器是否将 xvalue 静态转换为左值引用以绑定它?在这种情况下,“绑定”是什么意思?
  • "bind" 表示引用的名称此后将引用初始化程序指定的对象。所有引用都必须在创建时绑定。没有“编译器静态转换”或任何东西。
猜你喜欢
  • 2017-10-31
  • 1970-01-01
  • 2021-09-17
  • 1970-01-01
  • 2018-02-05
  • 2011-04-23
  • 2011-09-12
  • 2011-02-23
  • 2018-10-24
相关资源
最近更新 更多