c++:临时对象的特殊行为

标签 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&)

}

如果您想知道我是从哪里得到这个的,我正在尝试理解 move 构造函数,如 Dobb's. 上的一篇文章所述。

最佳答案

首先,请务必注意,您观察到的行为与 move 语义无关,也与 move 构造函数的存在与否无关。您可以在 C++03 编译器上运行示例并观察完全相同的行为。

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

如果您正在使用 Microsoft 的 VC 编译器,您可能会觉得这很奇怪。原因是 MSVC 有一个非标准扩展,它允许将右值绑定(bind)到对非 const 的左值引用。这是 IMO 的一个扩展,标准 C++ 不是这样工作的。

现在这就是说,当您提供一个临时值(右值)时,编译器别无选择,只能选择采用对 const 的左值引用的重载。重载对非 const 进行左值引用是不可行的,因为我之前写过。

现在在您的情况下,第二个重载是可行的,因为存在从 aClassaClassCatcher 的用户定义转换。该转换将返回 aClassCatcher 类型的临时对象,并且对 const 的左值引用可以绑定(bind)到临时对象。因此,您的第二个过载被选中。

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

关于c++:临时对象的特殊行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17008434/

相关文章:

python - tkinter( python ): assign class method to a key

javascript - 如何使用html5生成临时公钥

c++ - 将 .cpp 文件编译为程序内部的 EXE(EXE 文件)

c++ - 在使用中删除 boost 功能

c++ - 使用互斥锁和手动锁定互斥锁的区别

c++ - 将数据移入函数然后返回到它的来源时是否存在任何未定义的行为问题?

c++ - 如何使用 C++ (keybd_event) 发送 unicode 键

C# - 将列表框项目 move 到新的列表框

c++ - 将临时对象附加到对 const 的引用时出错

c++ - 关于将 string::swap() 与临时对象一起使用的问题