c:临时的特殊行为

在下面的代码中,为什么第一个调用解析为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的左值引用的那个是优选的,因为不需要转换.

上一篇:备忘录——IIS程序修改不生效Temporary ASP.NET


下一篇:C调用临时对象的函数