尝试调用移动分配运算符时,"operator="的重载不明确



我正在努力澄清理解移动语义,为此,我编写了以下代码。我使用一个原始指针作为数据成员,只是为了练习找到所有危险的地方,还应用了像copy&交换

#include <iostream>
#include <utility>
class Example {
protected:
int* intPtr;

public:
Example() : intPtr{nullptr} {
allocate();
std::cout << "Example() called" << "n";
}
Example(int value) : intPtr{nullptr} {
allocate();
assign(value);
std::cout << "Example(int) called" << "n";
}
~Example() {
deallocate();
std::cout << "~Example called" << "n";
}
Example(const Example& anExample) :
intPtr{anExample.intPtr ? new int(*anExample.intPtr) : nullptr} {
std::cout << "Example(const Example&) called" << "n";
}
Example(Example&& anExample) noexcept {
intPtr = anExample.intPtr;
anExample.intPtr = nullptr;
std::cout << "Example(Example&&) called" << "n";
}
Example& operator=(Example&& anExample) noexcept {
if(this != &anExample){
intPtr = anExample.intPtr;
anExample.intPtr = nullptr;
std::cout << "Move assignment op called" << "n";
}
return *this;
}

Example& operator=(Example anExample) {
std::swap(intPtr, anExample.intPtr);
std::cout << "Copy assignment op called n";
return *this;
}
void assign(int value) {
if (intPtr != nullptr && *intPtr!=value) 
*intPtr = value;
else {
std::cout << __FUNCTION__ << ": intPtr is either null, or its memory contains already the value you want.n";
}
}

private:
void allocate() {intPtr = new int{};}
void deallocate() {delete intPtr;}

friend std::ostream& operator<<(std::ostream& strm, const Example& anExample) {
return strm << *anExample.intPtr;
}

};
int main() {
Example ex1;
std::cout << "----------------" <<std::endl;
Example ex2{ex1};
std::cout << "----------------" <<std::endl;
Example ex3 = ex2; // invokes copy constructor
std::cout << "----------------" <<std::endl;
Example ex4;
std::cout << "----------------" <<std::endl;
ex4 = ex3; // invokes copy assignement operator
std::cout << "----------------" <<std::endl;
Example ex5 = std::move(ex1); // invokes move constructor
std::cout << "----------------" <<std::endl;
ex4 = std::move(ex5); // compilation error!
return 0;
}

最后一行给出以下错误

main.cxx:116:22: error: ambiguous overload for ‘operator=’ (operand types are ‘Example’ and ‘std::remove_reference<Example&>::type’ {aka ‘Example’})
116 |   ex4 = std::move(ex5);
|                      ^
main.cxx:36:12: note: candidate: ‘Example& Example::operator=(Example&&)’
36 |   Example& operator=(Example&& anExample) noexcept {
|            ^~~~~~~~
main.cxx:45:12: note: candidate: ‘Example& Example::operator=(Example)’
45 |   Example& operator=(Example anExample) {
|            ^~~~~~~~

为什么右手边的类型是std::remove_reference<Example&>::type。我在这里做错了什么?如何正确调用移动分配运算符?欢迎其他任何评论。

Example& operator=(Example anExample)是一个通用赋值运算符。它复制左值并移动右值。

如果要区分复制和移动分配,则需要Example& operator=(const Example & anExample)

或者,您可以删除Example& operator=(Example&& anExample)

相关内容

最新更新