1

在移动赋值运算符中,我应该使用 std::move 还是 std::swap?

我做了:

void Swap(Image& Img) {/*Swap everything here*/}

Image& Image::operator = (const Image &Img)
{
    if (this != &Img) Img.Swap(*this); //Compiler error for copy assignment.. no match for swap taking const..
    return *this;
}

Image& Image::operator = (Image&& Img)
{
    Img.Swap(*this);
    return *this;
}

假设我有两个图像 I 和 J 并且我做:

I = std::move(J);

发生的情况是来自 I 和 J 的数据被交换,所以现在 J 具有 I 的像素,反之亦然。这是正常的吗?我以为移动任务应该是偷窃和破坏?这样当 J 移动到 I 时,我得到 J 的内容而 J 被销毁?但是我在网上看到了这些例子

我可以在移动构造函数中看到相同的代码,但它如何在赋值中工作?这似乎没有意义:S

std::move 也应该在移动构造函数中使用吗?如果我在构造函数中使用 std::move 它会使我的程序崩溃:

Image::Image(Image&& Img) : Pixels(), Info(), /*Default everything*/
{
    this->Swap(Img);
    Img.Pixels.clear();
}

上面的构造函数有效。但是,如果我在构造函数中使用 std::move :

Image::Image(Image&& Img) : Pixels(std::move(Img.Pixels)), Info(std::move(Img.Info)), /*move everything*/
{
    //Do I need to set Img's values to default? Or does std::move do that?
}

尝试使用已移动的对象时,这将使我的程序崩溃:

Image I = Image("C:/Image.bmp");
Image J = std::move(I);
I.Draw(...); //Crashes program if using std::move. If using the swap version of the constructor, it works. I assume it's because swap version defaults everything.
4

1 回答 1

3

如果您支持有效的交换和移动构造,那么您应该只有一个赋值运算符,按值:

Foo & operator=(Foo rhs) { rhs.swap(*this); }

如果用户传递了一个常量引用,那么无论如何您都需要制作副本。如果用户传递一个右值,那么局部变量的构造rhs很便宜。

换句话说,在复制/移动构造函数、复制/移动赋值和交换这三个中,您只需要深入实现两个(并且这两个应该是构造函数之一)。

于 2013-03-11T03:42:46.857 回答