当需要移动赋值运算符时,为什么编译器要寻找复制赋值运算符?

HCS*_*CSF 2 c++

#include <utility>

class A {
    int* ptr;
public:
    A() {
        ptr = new int[10];
    }

    A(A&& rhs) {
        this->ptr = rhs.ptr;
        rhs.ptr = nullptr;
    }

    ~A() {
        if (ptr) delete[] ptr;
    }
};

int main() {
    A a1;
    A a2;
    a2 = std::move(a1);
}
Run Code Online (Sandbox Code Playgroud)

GCC 11 抱怨复制赋值运算符被删除:

<source>: In function 'int main()':
<source>:23:22: error: use of deleted function 'constexpr A& A::operator=(const A&)'
   23 |     a2 = std::move(a1);
      |                      ^
<source>:3:7: note: 'constexpr A& A::operator=(const A&)' is implicitly declared as deleted because 'A' declares a move constructor or move assignment operator
    3 | class A {
      |       ^
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)

然后,在我定义了移动赋值运算符(不是复制赋值运算符)之后,它编译得很好。那么,这意味着编译器确实正在寻找移动赋值运算符,这正是我所期望的。我不明白为什么当隐式删除移动赋值运算符时,编译器会寻找复制赋值运算符。任何想法?或者这只是编译器发出的错误消息?

Dan*_*ica 5

你的解释并不完全正确。编译器并没有特别寻找operator=(A&&). 它只是在寻找任何operator=可以被要求执行该任务的人。

现在,移动赋值运算符operator=(A&&)根本不存在。但是,复制赋值运算符operator=(const A&)确实存在,但它被定义为已删除。

因此,复制赋值运算符是唯一可用于该赋值的运算符(因为常量左值引用可以绑定右值)。编译器尝试使用它,但发现它已被删除,从而触发编译错误。