Chr*_*ong 5 c++ rvalue lvalue ref-qualifier
我试图找出为什么以下代码片段调用 LValue 强制转换运算符重载:
#include <iostream>
class Foo
{
public:
Foo(int i = 0) : i(i) {}
operator const int& () const &
{
std::cout << "lvalue\n";
return i;
}
operator int () const &&
{
std::cout << "rvalue\n";
return i;
}
int i = 0;
};
Foo Fool()
{
return Foo(5);
}
int main()
{
const int& i = Fool();
const int j = Fool();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
目前的输出是:
左值
右值
但根据我的理解,Fool()返回一个rvalue并且由于const&可以绑定到rvalues所以不需要构造一个lvalue Foo。
谁能解释一下为什么lvalue要建造?我相信这是一个悬而未决的lvalue。
好的,这里要注意的是,重载解析仅考虑 . 的一个转换函数i。它们并不都参与,因此不能使用参考限定符来区分它们。对于绑定参考的情况
\n\n\n[over.match.ref]
\n\n在 [dcl.init.ref] 中指定的条件下,引用可以直接绑定到将转换函数应用于初始化表达式的结果。重载解析用于选择要调用的转换函数。假设 \xe2\x80\x9creference to cv1 T\xe2\x80\x9d\n 是正在初始化的引用的类型,而 \xe2\x80\x9ccv S\xe2\x80\x9d 是初始化器的类型\n表达式,其中 S 为类类型,候选函数选择如下:
\n\n\n
\n- 考虑S及其基类的转换函数。那些未隐藏在 S\n 中并产生对 cv2 T2\xe2\x80\x9d 的类型 \xe2\x80\x9clvalue 引用的非显式转换函数(当初始化\n 左值引用或对函数的右值引用时)或 \ xe2\x80\x9ccv2 T2\xe2\x80\x9d 或\n \xe2\x80\x9cr对 cv2 T2\xe2\x80\x9d 的值引用(初始化右值引用或\n 对函数的左值引用时),其中 \xe2 \x80\x9ccv1 T\xe2\x80\x9d 与 \xe2\x80\x9ccv2 T2\xe2\x80\x9d 引用兼容,是候选函数。对于直接初始化,那些未隐藏在 S 中并产生对 cv2 T2\xe2\x80\x9d 的类型 \xe2\x80\x9clvalue 引用的显式转换函数(当\n 初始化左值引用或右值引用时)函数)\n 或 \xe2\x80\x9cr 对 cv2 T2\xe2\x80\x9d 的值引用(初始化右值引用\n 或对函数的左值引用时),其中 T2 与 T 或\n 的类型相同通过限定转换转换为类型 T 也是候选函数。
\n
根据粗体文本,初始化时i,我们唯一的候选者是operator int const&。因此重载决策要么在这里通过,要么完全失败。但它无法选择operator int,因为甚至没有考虑到这一点。它成功是因为 const 限定的左值引用可以绑定到对象参数。
另一方面,为了初始化一个值
\n\n\n\n\n[超过匹配转换]
\n\n在 [dcl.init] 中指定的条件下,作为非类类型对象初始化的一部分,可以调用转换函数将类类型的初始值设定项表达式转换为该类型的类型正在初始化的对象。重载解析用于选择要调用的转换函数。假设 \xe2\x80\x9ccv1 T\xe2\x80\x9d\n 是正在初始化的对象的类型,而 \xe2\x80\x9ccv S\xe2\x80\x9d 是初始化表达式的类型,对于 S 类类型,候选函数的选择如下:
\n\n\n
\n- 考虑S及其基类的转换函数。那些未隐藏在 S\n 中并产生类型 T 或可通过标准转换序列转换为类型 T 的类型的非显式转换函数是候选函数。对于直接初始化,那些未隐藏在 S 中且产生类型 T 或可通过限定转换转换为类型 T 的类型的显式转换函数也是候选函数。返回 cv 限定类型的转换函数被视为在选择候选函数的过程中产生该类型的 cv 非限定版本。对返回 \xe2\x80\x9c 对 X\xe2\x80\x9d 的引用的转换函数的调用是 X 类型的泛左值,因此这样的转换函数被认为在选择过程中产生 X候选函数。
\n
因此,在初始化时,j两个转换函数都作为重载参与,这里引用限定符会产生影响。
你确实在这里得到了一个悬而未决的参考,这似乎是由于语言中的一个黑暗角落造成的。第一个引用段落中的项目符号可能可以进行改进,以更好地考虑const lvlaue 引用的绑定。由于这些也可能绑定到临时运算符,因此理想情况下,您的第二个转换运算符可以成为更好规则下的候选者。
\n| 归档时间: |
|
| 查看次数: |
1031 次 |
| 最近记录: |