窃取移动构造函数内部

发布于 2024-11-17 08:27:18 字数 695 浏览 10 评论 0原文

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

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_);
}

是否有任何缺点这?是否有一种不需要预处理器的更清洁的解决方案?

During the implementation of the move constructor of a toy class, I noticed a pattern:

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;
}

The pattern obviously being:

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

So I wrote a preprocessor macro to make stealing less verbose and error-prone:

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

Now the implementation looks as following:

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

Are there any downsides to this? Is there a cleaner solution that does not require the preprocessor?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

溺ぐ爱和你が 2024-11-24 08:27:18

以下是推荐的模式:

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 类定义中声明为数据成员的顺序相同。我发现主体中初始化程序列表的重复没有任何问题。这是必要的第二步。没有必要把它隐藏起来。

Here is the recommended pattern:

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;
}

Naturally if the data members are scalar types, the std::move isn't needed. But if you're copying this pattern around, it is helpful to include the move anyway so that when the member data aren't scalar, the std::move doesn't get forgotten.

Also if the member data have actual move constructors, then you can simply omit the body:

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

And if you want to generalize to types that don't have move constructors, but do have a resource-less default constructed state, you can:

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();
}

I recommend ordering these statements in the same order they are declared as data members in the array2D class definition. And I find nothing wrong with the repetition of the initializer list in the body. It is a necessary and second step. There is no need to sweep it under the rug.

帅哥哥的热头脑 2024-11-24 08:27:18

使用 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_);

How about using template:

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

Usage:

MOVE(data_, that.data_);

@Fred, from your comment, if you want to avoid mentioning data member twice, then:

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

Usage:

STEAL(data_);
伤感在游骋 2024-11-24 08:27:18

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

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

    this->swap(that);
}

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

array2D(array2D&& that)
: array2D() {
    this->swap(that);
}

Initialize your own members to default, and then swap.

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

    this->swap(that);
}

Even cleaner (if your compiler supports it)

array2D(array2D&& that)
: array2D() {
    this->swap(that);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文