将int &&传递给f(int &&)

Jor*_*nzo 20 c++ c++11

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

void f(int &&);

int && i = 5;

f(i);
Run Code Online (Sandbox Code Playgroud)

这不是有点违反直觉吗?

我希望i是一个右值引用,所以能够传递给它f().但我得到一个错误;

没有任何已知的转化率从intint &&

所以我猜i在申报后不是左值参考?

Gal*_*lik 28

我明白你为何感到困惑.要记住的是,只要有变量名,就有l值.

所以当你说:

int i = 0; // lvalue (has a name i)
Run Code Online (Sandbox Code Playgroud)

并且

int&& i = 0; // lvalue (has a name i)
Run Code Online (Sandbox Code Playgroud)

那么区别是什么呢?

所述int&&可仅结合一个r值,从而:

int n = 0;
int i = n; // legal
Run Code Online (Sandbox Code Playgroud)

int n = 0;
int&& i = n; // BAD!! n is not an r-value
Run Code Online (Sandbox Code Playgroud)

然而

int&& i = 5; // GOOD!! 5 is an r-value
Run Code Online (Sandbox Code Playgroud)

因此,当传递if()此示例时,您传递的是l值,而不是r值:

void f(int &&);

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

f(i); // won't accept l-value
Run Code Online (Sandbox Code Playgroud)

这种情况实际上比我在这里提出的要复杂一些.如果您对更全面的解释感兴趣,那么这个参考文献非常透彻:http://en.cppreference.com/w/cpp/language/value_category

  • 很棒的解释. (2认同)

Yam*_*vic 19

这里有一个基本的区别是aa绑定a.例如:

void f(int &&);
Run Code Online (Sandbox Code Playgroud)

声明一个接受一个参数的函数,该参数只能用对(转换为)的rvalue引用进行初始化int.

int && i = 5;
Run Code Online (Sandbox Code Playgroud)

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

f(i);
Run Code Online (Sandbox Code Playgroud)

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

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

f(std::move(i));
Run Code Online (Sandbox Code Playgroud)

  • 这几乎是**一个很好的答案,但略有不准确._"声明一个只能赋予对int的rvalue引用的左值."_不,它不能被"赋值"任何东西,当然也不是rvalue引用(因为赋值给引用实际上是指定它绑定的东西,但这是初始化而不是分配).它声明了一个左值引用类型的左值"i",它只能用一个rvalue(不是rvalue-reference,一个rvalue)**初始化**. (4认同)
  • @LogicStuff,如果你作为右值转发,是的,但这在这里毫无意义.如果你知道你想要一个右值,请使用`std :: move`.如果要将某些内容转发为左值或右值,则根据其原始值类别,使用`std :: forward`.编写`std :: forward <int>(i)`而不是`std :: move(i)`是完全没有意义的. (2认同)

Dav*_*aim 17

它有名字吗?
它可以解决吗?

如果两者的答案都是"是",那么它就是L值.

在这个片段中:i有一个名字,i有一个地址(你可以写&i),所以它是一个l值.

f(&&)获取r值引用作为参数,因此您需要将l值转换为r值引用,这可以通过以下方式完成std::move.

f(std::move(i));
Run Code Online (Sandbox Code Playgroud)