12

在一个玩具类的移动构造函数的实现过程中,我注意到了一个模式:

array2D(array2D&& that)
{
    data_ = that.data_;
    that.data_ = 0;

    height_ = that.height_;
    that.height_ = 0;

    width_ = that.width_;
    that.width_ = 0;

    size_ = that.size_;
    that.size_ = 0;
}

模式显然是:

    member = that.member;
    that.member = 0;

所以我写了一个预处理器宏来让窃取变得不那么冗长和容易出错:

#define STEAL(member) member = that.member; that.member = 0;

现在实现如下所示:

array2D(array2D&& that)
{
    STEAL(data_);
    STEAL(height_);
    STEAL(width_);
    STEAL(size_);
}

这有什么缺点吗?是否有不需要预处理器的更清洁的解决方案?

4

3 回答 3

12

这是推荐的模式:

array2D(array2D&& that)
    : data_(std::move(that.data_)),
      height_(std::move(that.height_)),
      width_(std::move(that.width_)),
      size_(std::move(that.size_))
{
    that.data_ = 0;
    that.height_ = 0;
    that.width_ = 0;
    that.size_ = 0;
}

当然,如果数据成员是标量类型,std::move则不需要。但是,如果您要复制此模式,那么包含move无论如何都会很有帮助,这样当成员数据不是标量时,std::move就不会被遗忘。

此外,如果成员数据具有实际的移动构造函数,那么您可以简单地省略主体:

array2D(array2D&& that)
    : data_(std::move(that.data_)),
      height_(std::move(that.height_)),
      width_(std::move(that.width_)),
      size_(std::move(that.size_))
{
}

如果您想推广到没有移动构造函数但确实具有无资源默认构造状态的类型,您可以:

array2D(array2D&& that)
    : data_(std::move(that.data_)),
      height_(std::move(that.height_)),
      width_(std::move(that.width_)),
      size_(std::move(that.size_))
{
    that.data_ = Data();
    that.height_ = Height();
    that.width_ = Width();
    that.size_ = Size();
}

array2D我建议按照它们在类定义中声明为数据成员的顺序对这些语句进行排序。而且我发现在正文中重复初始化列表没有任何问题。这必要的第二步。没有必要把它扫到地毯下。

于 2011-06-27T12:23:31.240 回答
9

如何使用template

template<typename T> inline
void MOVE(T &dst, T &src)
{
  dst = src;
  src = 0;
}

用法:

MOVE(data_, that.data_);

@Fred,根据您的评论,如果您想避免两次提及数据成员,那么:

#define STEAL(X) MOVE(X, that.X)

用法:

STEAL(data_);
于 2011-06-27T11:51:38.190 回答
5

将您自己的成员初始化为默认值,然后swap.

array2D(array2D&& that)
{
    data_ = 0;    
    height_ = 0;    
    width_ = 0;    
    size_ = 0;

    this->swap(that);
}

更干净(如果你的编译器支持它)

array2D(array2D&& that)
: array2D() {
    this->swap(that);
}
于 2011-06-27T11:55:39.943 回答