【问题标题】:Passing int&& to f(int&&)将 int&& 传递给 f(int&&)
【发布时间】:2016-02-10 11:35:13
【问题描述】:

这里到底发生了什么?为什么这是一个错误?

void f(int &&);

int && i = 5;

f(i);

是不是有点反直觉?

我希望i 是一个右值引用,因此能够将它传递给f()。但我得到一个错误;

没有从intint && 的已知转换

所以我猜i 不是声明后的右值引用?

标签: c++ c++11


【解决方案1】:

我明白你为什么感到困惑。要记住的是,只要您有一个变量名,您就有一个 l-value

所以当你说:

int i = 0; // lvalue (has a name i)

还有

int&& i = 0; // lvalue (has a name i)

那么有什么区别呢?

int&& 只能绑定到一个 r-value 所以:

int n = 0;
int i = n; // legal

但是

int n = 0;
int&& i = n; // BAD!! n is not an r-value

但是

int&& i = 5; // GOOD!! 5 is an r-value

因此,在此示例中,当将 i 传递给 f() 时,您传递的是 l-value,而不是 r-value

void f(int &&);

int&& i = 5; // i is an l-value

f(i); // won't accept l-value

实际情况比我在这里介绍的要复杂一些。如果您对更全面的解释感兴趣,那么此参考资料非常详尽:http://en.cppreference.com/w/cpp/language/value_category

【讨论】:

  • 我认为这是一个很好的答案。我建议的唯一一点是,也许在第一句话中让它更清楚一点,因为通常this 可以被认为是一个变量(虽然它不是真的),但是this 是一个prvalue。你能想出什么好的方法来解决这个问题,或者它是否真的相关?
  • @YamMarcovic 我知道情况可能会更复杂一些,但我认为出于学习目的,最好展示与 OP 试图理解的示例简单且相关的内容。我要做的是添加一个链接以获取更多信息。
  • @Galik 听起来很合理。谢谢。
【解决方案2】:

is abinds a 之间有一个基本的区别。例如:

void f(int &&);

声明一个接受参数的函数,该参数只能使用对(类型可转换为)int 的右值引用进行初始化。

int && i = 5;

声明一个左值,该左值只能使用对(类型可转换为)int 的右值引用进行初始化。因此,简单来说,

f(i);

尝试将一个对int 的左值引用传递给一个只接受对int 的右值引用的函数。所以它不会编译。

要告诉编译器将左值转换为右值,从而在适用的情况下使用移动构造函数(尽管在int 的情况下不是),您可以使用std::move()

f(std::move(i));

【讨论】:

  • 在这种情况下,我会添加有关 std::move 的信息。
  • @Zereges 好主意。已添加。
  • 几乎是一个很好的答案,但有点不准确。 “声明一个只能分配给 int 的右值引用的左值。” 不,它不能被“分配”任何东西,当然不是右值引用(因为分配给引用实际上分配给事物它是必然的,但这是初始化而不是赋值)。它声明了一个右值引用类型的左值i,只能用右值(不是右值引用,右值)初始化
  • @LogicStuff,如果您作为右值转发,是的,但这在这里毫无意义。如果你知道你想要一个右值,请使用std::move。如果您想将某些内容作为左值或右值转发,具体取决于其原始值类别,请使用std::forward。写std::forward<int>(i) 而不是std::move(i) 完全没有意义。
  • @YamMarcovic 是的,i 是一个左值和一个右值引用
【解决方案3】:

它有名字吗?
是否可寻址?

如果两者的答案都是“是”,那么它就是 L 值。

在这个sn-p中:i有一个名字,i有一个地址(你可以写&i),所以它是一个左值。

f(&&)获取r-value-reference作为参数,所以需要将l-value转为r-value reference,可以通过std::move完成。

f(std::move(i));

【讨论】:

  • 注意:还有一些左值没有名字。此外,“它是否可寻址”是一个循环定义。我认为“可寻址”是指“可以将一元 & 应用于它吗?”;但是一元 & 的定义包括它只能应用于左值!
猜你喜欢
  • 2020-11-19
  • 1970-01-01
  • 2021-06-01
  • 2013-07-13
  • 2018-05-01
  • 1970-01-01
  • 2020-07-24
  • 2014-06-03
  • 2020-06-16
相关资源
最近更新 更多