C++11移动构造函数

5
我正在查看一些我继承下来的代码,其中有一个矩阵类在C++中实现了2D矩阵并拥有移动构造函数和赋值运算符。

它的实现方式如下:

template<typename T, int rows, int cols>
class matrix_data {
    ...
    std::unique_ptr<T[]> data_;
    // Some definitions
    typedef matrix_data<T, rows, cols> this_type

    matrix_data(this_type && other)
    {
        std::swap(data_, other.data_);
    }
};

现在,我不确定为什么数据指针在这里被交换了。我认为应该是这样的:
data_ = std::move(other.data_);

我猜想使用swap还可以,因为other实例在移动后应该已经处于无效状态了。

我的问题是,我能否用data_ = std::move(other.data_);来替换这个语句?是否有一些unique_ptr的删除操作导致必须使用交换而不是移动呢,即如果我执行移动操作,原始数据是否会被正确删除?


2
通过使用一个已知即将过期的临时变量来交换对象内容,可以确保清理对象当前的数据成员。在这种情况下可能并不是必要的,但这是这种操作的常见模式。 - Richard Critten
2
如果您从对象中添加或删除数据成员,则需要更改的函数就会减少一个。析构函数可能需要更改,但移动构造函数不需要,这使得代码更改更少出错。此外,std::swap通常可以提供强异常保证,然后可以传播到移动构造函数。 - Richard Critten
2
最佳解决方案是 matrix_data(this_type && other) = default;。使用 std::swap 没有意义,它会做更多的工作。 - juanchopanza
1
@Luca 是的,这正是正确的做法。事实上,你甚至不需要添加移动构造函数。因此,最好的解决方案是:删除构造函数。 - juanchopanza
2
如果类的 ... 部分包含其他构造函数,这是相当可能的,你将必须明确要求移动构造函数(但可以使用 = default 版本)。 - Bo Persson
显示剩余4条评论
1个回答

2
回答你的问题:
是的,你可以使用替换来代替交换。
data_ = std::move(other.data_);

但正如评论所指出的那样,如果您没有实现移动构造函数,只要您没有实现复制构造函数、复制赋值运算符、移动赋值运算符或析构函数,这种情况就已经发生了。如果您已经实现了上述其中之一,将移动构造函数标记为=default也可以完成工作。
在这种情况下,交换对象的内容确实是不必要的,因为这是一个(移动)构造函数,this->data_并没有指向任何先前分配的内存位置,在指针被覆盖后应该被释放。
因此,在实现移动赋值运算符时通常会进行交换,因为在这种情况下,this->data_通常保存指向需要在某个时候释放的内存位置的指针。通过将此指针放入移动自的对象中,当调用移动自的对象的析构函数时,它所指向的内存将被释放。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接