尝试调用移动赋值运算符时“operator=”的不明确重载
Ambiguous overload for ‘operator=’ when trying to invoke the move assignment operator
我试图澄清-理解移动语义,为此,我编写了以下代码。我使用原始指针作为数据成员只是为了练习找到所有的危险点,并且还应用了像复制和交换这样的习语。
#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)
。
我试图澄清-理解移动语义,为此,我编写了以下代码。我使用原始指针作为数据成员只是为了练习找到所有的危险点,并且还应用了像复制和交换这样的习语。
#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)
。