在下面的代码中,为什么第一个调用解析为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.
中的文章所述答案 0 :(得分:5)
首先,重要的是要注意您正在观察的行为与移动语义无关,也与移动构造函数的存在与否无关。您可以在C ++ 03编译器上运行您的示例,并观察完全相同的行为。
您正在观察的行为的解释是,对非const
(aClass&
)的左值引用只能绑定到左值,而左值引用const
({{1} })可以绑定到左值和右值(但不允许修改它们绑定的对象,因为它们是对const aClassCatcher&
的引用)。
如果您正在使用Microsoft的VC编译器,那可能听起来很奇怪。原因是MSVC具有非标准扩展,允许绑定rvalues以对非const
的引用进行左值化。这是IMO的一个坏扩展,而这不是标准C ++的工作方式。
现在这样说,当你提供一个临时值,这是一个rvalue时,编译器没有机会选择带有左值引用const
的重载。由于我之前所写的内容,对非const
进行左值引用的重载根本不可行。
现在,在您的情况下,第二次重载是可行的,因为存在从const
到aClass
的用户定义转换。该转换将返回aClassCatcher
类型的临时值,aClassCatcher
的左值引用可以绑定到临时值。因此,选择了第二个重载。
另一方面,当你提供一个左值时,两个重载都是可行的,但接受非const
左值引用的那个是首选,因为不需要转换。