c ++:临时的特殊行为

use*_*604 3 c++ move temporary

在下面的代码中,为什么第一个调用会解析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&)

}
Run Code Online (Sandbox Code Playgroud)

如果你想知道我在哪里遇到这个,我试图理解移动构造函数,如Dobb的文章所述.

And*_*owl 5

首先,重要的是要注意您观察到的行为与移动语义无关,也与移动构造函数的存在与否无关.您可以在C++ 03编译器上运行您的示例并观察完全相同的行为.

您正在观察的行为的解释是对non const(aClass&)的左值引用只能绑定到左值,而对const(const aClassCatcher&)的左值引用可以绑定到左值和右值(但不允许修改它们绑定的对象,因为他们是参考const).

如果您正在使用Microsoft的VC编译器,那可能听起来很奇怪.原因是MSVC具有非标准扩展,允许绑定rvalues以将值引用为非值const.这是IMO的一个不好的扩展,而这不是标准C++的工作方式.

现在这个说,当你提供一个临时的,这是一个rvalue时,编译器没有机会选择带左值引用的重载const.const由于我之前所写的内容,对非值进行左值引用的重载根本不可行.

现在,在你的情况下,第二超载是可行的,因为有来自用户定义的转换aClassaClassCatcher.该转换将返回临时类型aClassCatcher,并且左值引用const可以绑定到临时值.因此,您的第二个重载被选中.

另一方面,当您提供左值时,两个重载都是可行的,但是接受非左值引用的那个const是优选的,因为不需要转换.