复制/移动分配混淆

时间:2013-03-11 03:35:20

标签: c++ c++11

在移动赋值运算符中,我应该使用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有两个图像:

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.

1 个答案:

答案 0 :(得分:3)

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

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

如果用户传递了const-reference,那么无论如何都需要进行复制。如果用户传递了一个rvalue,那么构造局部变量rhs很便宜。

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