函数内的 rvalue 引用参数类型是什么?

5

我这里有一个非常简单的函数定义:

void testRvalue(int&& r)
{
    printf("rvalue ref is called\n");
    testRvalue(r); // this line gives "no known conversion from 'int' to 'int &&' for 1st argument"
}

我指的是这个函数内部,r 的类型是什么?它不是 int&& 吗?(因为参数是 int&& r,所以为什么 r 不是 int&& 类型?)如果是这样,为什么不能将这个 r 传递给需要 int&& 类型参数的函数本身? r 究竟是什么类型?int&& 还是 int?如果是 int,为什么?
1个回答

10

一个非常好的阅读材料是值类别

是的,变量r的类型确实是int&&。但是在这里更重要的是表达式和:

每个C++表达式(运算符及其操作数、文字、变量名等)都具有两个独立的属性:一种类型和一种值类别。每个表达式都有一些非引用类型,并且每个表达式都属于三个主要值类别之一:prvalue、xvalue和lvalue。

表达式r是一个lvalue:

lvalue

以下表达式是左值表达式:

  • 变量的名称[...],无论类型如何。即使变量的类型是右值引用,由其名称组成的表达式也是左值表达式;

Rvalue引用可以绑定到prvalue或xvalue,但不可以绑定到lvalue,因此如果您想将rvalue引用绑定到r,则需要将r转换为xvalue。这可以使用std::move完成,尽管它的名称是一个强制转换。

你可以这样轻松地推理: 如果它有一个名称,那么它就是 lvalue (即使该 id 的类型是 rvalue 引用)。你不能将 rvalue 引用(原则上应该绑定到临时对象)绑定到有名称的东西上。具有名称的东西可以被重复使用。你需要 std::move 来从该 lvalue 中启用移动。

关于消息中说的 "no known conversion from 'int'"。如上所示,表达式 r 的类型为 int,然而更合适的诊断消息应该是类似于:“rvalue 引用无法绑定到 lvalue”。

事实上,新版的 Clang 和 GCC 给出了更好的消息:

GCC:

error: cannot bind rvalue reference of type 'int&&' to lvalue of type 'int'

Clang:

candidate function not viable: expects an rvalue for 1st argument


3
我花了一段时间才意识到整个事情的核心是“表达式”,而不是变量。 - xtofl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接