关于右值引用的困惑:它的类型是什么? 左值

问题描述

在这里一个非常简单的 func 定义:

List<int> _bytes;
Future getimage() async {
    final image = await ImagePicker().getimage(source: ImageSource.camera,imageQuality: 5);
    _bytes = await image.readAsBytes();  
final addToDb = Article.withFields( _bytes).upsert();
}

我的意思是...在这函数中,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类型?)如果是这样为什么我不能通过这个{{1} } 到这个 func 本身,它接受一个 int&& 类型作为参数?

r 的类型究竟是什么? int&& 还是 r?如果int&&,为什么???

解决方法

非常好的阅读Value categories

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

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

表达式 r 是一个左值:

左值

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

  • 变量名 [...],与类型无关。即使变量的类型是右值引用,由其组成的表达式 name 是一个左值表达式;

Rvalue 引用可以绑定到 prvalues 或 xvalue 但不能绑定到 lvalues 所以如果你想绑定一个右值引用到 r 你需要将 r 转换为一个 xvalue。这是通过 std::move 完成的,尽管它的名字只是一个演员表。

你可以很容易地这样推理:如果它有一个名字,那么它就是一个左值(即使那个 id 的类型是右值引用)。您不能将右值引用(原则上应该绑定到临时对象)绑定到具有名称的内容。有名字的东西可以重复使用。您需要 std::move 才能启用从该左值移动。

关于“没有已知的来自‘int’的转换”的消息。如上所示,表达式 r 的类型是 int,但是更合适的诊断消息应该是:“右值引用不能绑定到左值”。

而且确实较新的 clang 和 gcc 提供了更好的信息:

gcc

错误:无法将“int&&”类型的右值引用绑定到“int”类型的左值

叮当声

候选函数不可行:第一个参数需要右值