rvalue 来自哪里?

3
我正在学习引用和值类别,因为后者在一些C++错误中被提到。
我有一个函数referenceToDouble,它接受对double的引用。从观看this video on value categories,我相信下面的leftright是指向double的左值引用。
main中,当我创建类型为double的变量ab时,我不会出现错误。下面的代码显示了类型为floatab,这给了我一个错误。
#include <cassert>

double referenceToDouble(double& left, double& right) {
    if (left >= right) {
        right = left;
    }
    else {
        left = right;
    }

    return left;
}

int main() {
    float a = 55.5;
    float b = 55.5;

    assert(55.5 == referenceToDouble(a, b));
}

当我将ab的数据类型转换为float时,出现了这个错误。
checkReferences.cpp: In function 'int main()':
checkReferences.cpp:18:35: error: cannot bind non-const lvalue reference of type 'double&' to an rvalue of type 'double'
   18 |  assert(55.5 == referenceToDouble(a, b));
      |                                   ^
checkReferences.cpp:3:34: note:   initializing argument 1 of 'double referenceToDouble(double&, double&)'
    3 | double referenceToDouble(double& left, double& right) {
      |                          ~~~~~~~~^~~~

我的问题是:

  • rvalue是从哪里来的?

  • 是否有一个临时变量包含从float转换而来的adouble值?这个临时变量是否是rvalue

  • 还是错误指的是55.5,它是一个字面量,因此是rvalue?

  • 返回类型在这里没有参与吗?我认为不是,因为这是按值返回而不是按引用返回。

我尝试了阅读类似错误的答案,但我无法消除我的疑虑。我也认为我知道解决方案(使用double),但我正在尝试理解底层发生了什么。


我认为这归结于一个关于你特定编译器警告措辞和编译器工作方式的问题,因为当我在 https://godbolt.org 上尝试 Clang 13.0.0 或 GCC 11.2 时,并没有提到 double 右值。你使用的是哪个特定的编译器? - David Grayson
1
@DavidGrayson 你确定吗?https://godbolt.org/z/T9zYrvo17 - Retired Ninja
实际上,当我点击您的链接时,它显示“类型为'float'的值”,而不是“类型为'double'的rvalue”。 - David Grayson
我正在使用 g++,更具体地说是 g++ (GCC) 9.3.1 20200408 - heretoinfinity
1个回答

2
是否有一个临时变量,其中包含从float转换而来的double值的临时变量?这个临时变量是否是rvalue?
是的。类型为double&的left和right不能直接绑定到float。首先必须将它们转换为double,这些是临时变量(rvalues),无法绑定到非const的lvalue引用。如果将left和right的类型更改为const double&,则可以正常工作。转换后的double临时变量(rvalues)可以绑定到const的lvalue引用。

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