use*_*756 11 c++ overloading reference rvalue-reference lvalue-to-rvalue
今天我大致遇到了以下代码:
\n#include <iostream>\n\nvoid f(float&& f) { std::cout << f << "f "; }\nvoid f(int&& i) { std::cout << i << "i "; }\n\nint main()\n{\n int iv = 2; float fv = 1.0f;\n f(2); f(1.0f);\n f(iv); f(fv);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n正如预期的那样,前两个 f 调用 print 2i 1f
。
现在对于第二行,我预计它要么根本不编译,因为 iv 和 fv 不是临时变量(因此不能绑定到 r 值引用),要么它创建要传递给函数的变量的副本,从而打印2i 1f
再次打印。
然而,不知何故它打印2f 1i
,这几乎是我最没想到的事情。
如果将代码复制到 cppinsights 中,它会将调用转换为
\nf(static_cast<float>(iv));\nf(static_cast<int>(fv));\n
Run Code Online (Sandbox Code Playgroud)\n所以它看起来非常有意地将整数转换为浮点数,然后将浮点数转换为整数,但我不知道为什么这样做,也不知道如何谷歌。为什么会出现这种情况?导致这个结果的规则是什么?
\n程序的行为可以从引用初始化来理解。
[实施例6:
Run Code Online (Sandbox Code Playgroud)double d2 = 1.0; double&& rrd2 = d2; // error: initializer is lvalue of related type int i3 = 2; double&& rrd3 = i3; // rrd3 refers to temporary with value 2.0
-结束示例]
在这里我们讨论为什么void f(int&& i)
调用不可行f(iv)
。
左值iv
无法绑定到调用i
中的右值引用参数,因此重载不可行。基本上,这是不允许的,因为它是相关类型的左值。void f(int&& i)
f(iv)
f(int&&)
int&& i = iv;
iv
下面我们讨论一下为什么void f(float&& i)
调用是可行的f(iv)
。
对于调用f(iv)
,重载是可行的,因为这里首先将void f(float&& f)
初始化表达式隐式转换为目标 type( ) 的纯右值,然后可以发生临时物化,以便参数可以绑定到该物化临时值(这是一个xvalue)。iv
float
f
2.0f
类似地,对于 call f(fv)
,重载void f(float&& i)
也是不可行的,因为fv
它是相关类型的左值。对于调用,可以使用f(fv)
重载void f(int&& i)
,因为首先初始化器被隐式转换为纯右值,然后发生临时物化,以便i
可以绑定到物化临时1
(类型为int
)。