繁体   English   中英

C ++ 11:为什么将右值引用参数隐式转换为左值

[英]C++11: Why rvalue reference parameter implicitly converted to lvalue

以下是我的问题的简单代码,

void overloaded (int&& x) {
  cout << "[rvalue]";
}

template <class T>
void fn (T&& x) {
  overloaded(x);
}

int main() {
    fn(0);
    return 0;
}

我有一个编译错误

无法将' int '左值绑定到' int&& '

  overloaded(x); 

我在这里感到困惑, x作为右值引用传递到fn() 但是,为什么在fn()overload()调用抱怨x是左值?

您不会“将x作为右值引用传递”,因为该语句实际上并没有意义。

以下是有关C ++中类型和表达式分类的一些事实:

  • 有对象类型和引用类型。 (还有其他几种类型。)

  • 变量可以是对象或引用。

  • 表达式具有类型,这些类型(几乎)总是对象类型,从不引用。 (这就是为什么您“将某些内容作为引用传递”的说法没有意义;您传递参数,而参数始终是表达式。)表达式可以是左值,左值或右值。

  • 左值引用绑定到左值。 右值引用绑定到右值。 (右值可以是prvalue或xvalue。)

  • 命名变量或参数的id表达式是左值。 (如果可以的话,这是“带有名称的事物”或“位置”。)

因此,在表达式overloaded(x) ,子表达式x是一个左值,并且不绑定到期望右值的函数(由于其右值引用参数)。

“左值引用”和“右值引用”中的“ l”和“ r”是指引用可以绑定的值的类别, 而不是命名该引用类型的变量的id表达式的类别。

您可以通过将左值转换为右值将左值转换为右值。 可以方便地将其封装到类型推断的强制转换助手std::move

第一, fnx参数不是r值引用, 而是“通用引用” (是的, 这很令人困惑 )。

二,给对象起一个名字,除非使用std::move (总是使其成为r值引用)或使用std::forward ,否则该名字不是r值,除非明确“固定”。 (在通用引用的情况下,将其转换回其原始类型)。 如果要避免投诉,请使用std::forward转发为原始类型:

template <class T>
void fn (T&& x) {
  overloaded(std::forward<T>(x));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM