操作符的模糊重载=使用移动分配和传递值复制分配

del*_*ver 8 c++ g++ move-semantics

如果我定义了一个复制赋值运算符,它使用class的pass by值来调用复制构造函数thing:

thing& operator= (thing x) {
Run Code Online (Sandbox Code Playgroud)

和同一个类的移动赋值运算符:

thing& operator= (thing&& x) {
Run Code Online (Sandbox Code Playgroud)

尝试调用移动分配会导致gcc出错:

error: ambiguous overload for ‘operator=’ (operand types are ‘thing’ and ‘std::remove_reference<thing&>::type {aka thing}’)
Run Code Online (Sandbox Code Playgroud)

但是,如果副本分配使用传递引用:

thing& operator= (thing& x) {
Run Code Online (Sandbox Code Playgroud)

编译很好,可以调用两个运算符.为什么是这样?

完整的C++ 11测试代码:

#include <iostream>
#include <utility>

using namespace std;

class thing {
    public:
        thing () { }
        thing (thing& x) {
            cout << "Copy constructor.\n";
        }
        thing (thing&& x) {
            cout << "Move constructor.\n";
        }
        thing& operator= (thing x) {
            cout << "Copy assign using pass by value.\n";
            return *this;
        }
        thing& operator= (thing&& x) {
            cout << "Move assign.\n";
            return *this;
        }
};


int main (void) {
    thing a, b;
// Invoke move assignment:
    a = move(b);
    return 0;
}                        
Run Code Online (Sandbox Code Playgroud)

101*_*010 5

  • 调用move(b)返回一个rvalue.

  • 和 都operator=(thing &&x)可以operator=(thing x)接受rvalues作为输入。

  • 因此,这两个重载是不明确的,编译器理所当然地抱怨,因为它无法在它们之间进行选择。

  • 这个问题有解决办法吗? (6认同)