在下面的代码中,为什么第一个调用解析为catchClass(aClass&)并在第二个调用catchClass(const aClassCatcher&)中将临时值作为参数给出
#include <iostream>
using namespace std;
class aClassCatcher{};
class aClass{
public:
operator aClassCatcher(){
return aClassCatcher();
}
};
void catchClass(aClass&){
cout << __FUNCSIG__ << endl;
}
void catchClass(const aClassCatcher&){
cout << __FUNCSIG__ << endl;
}
int main()
{
aClass aC;
catchClass(aC); // calls catchClass(aClass&)
catchClass(aClass()); // calls catchClass(const aClassCatcher&)
}
如果你想知道我在哪里遇到这个,我试图理解移动构造函数,如Dobb’s.文章所述
解决方法:
首先,重要的是要注意您观察到的行为与移动语义无关,也与移动构造函数的存在与否无关.您可以在C 03编译器上运行您的示例并观察完全相同的行为.
对你所观察到的行为的解释是对非const(aClass&)的左值引用只能绑定到左值,而对const(const aClassCatcher&)的lvalue引用可以绑定到左值和右值(但不允许修改)它们绑定的对象,因为它们是对const的引用.
如果您正在使用Microsoft的VC编译器,那可能听起来很奇怪.原因是MSVC具有非标准扩展,允许绑定rvalues以对非const进行左值引用.这是IMO的一个不好的扩展,而这不是标准C的工作方式.
现在这样说,当你提供一个临时的,这是一个rvalue时,编译器没有机会选择对const进行左值引用的重载.由于我之前所写的内容,对非const采用左值引用的重载根本不可行.
现在,在您的情况下,第二个重载是可行的,因为存在从aClass到aClassCatcher的用户定义转换.该转换将返回aClassCatcher类型的临时值,并且对const的lvalue引用可以绑定到temporaries.因此,您的第二个重载被选中.
另一方面,当你提供左值时,两个重载都是可行的,但是接受对非const的左值引用的那个是优选的,因为不需要转换.