【问题标题】:moving class (with no default constructor) inside the move constructor of another class在另一个类的移动构造函数中移动类(没有默认构造函数)
【发布时间】:2014-08-06 15:37:55
【问题描述】:

所以我有一个删除副本 ctor/assignment 的类,没有默认 ctor,并且有移动 ctor/assignment:

class A {
  int data_ = 0;

public:
    A(const A& other) = delete;
    A& operator=(const A& other) = delete;

    A(int data) : data_(data) {}
    ~A() {}

    A(A&& other) { *this = std::move(other); }
    A& operator=(A&& other) {
        if (this != &other) {
            data_ = other.data_;
            other.data_ = 0;
        }
        return *this;
    }
};

我有一个包含 A 的 B 类(也没有默认 ctor):

class B {
    A a;

public:
    B(const B& other) = delete;
    B& operator=(const B& other) = delete;

    B(int data) : a(data) {}
    ~B() {}

    B(B&& other) { *this = std::move(other); }
    B& operator=(B&& other) {
        if (this != &other) {
            a = std::move(other.a);
        }
        return *this;
    }
};

现在问题是 B 移动 ctor 无法编译,因为他说 A 没有默认构造函数,这真的很烦人,我不希望他在我调用 B 上的移动 ctor 时创建一个新的 A 实例,我想让它动起来!

所以我可以做两件事:

B(B&& other) : a(std::move(other.a)) { *this = std::move(other); }

这行不通,因为在移动任务中,他会尝试再次移动 A.. 同样如果“this == &other == true”,他现在会将 A 从自己身上移开,造成 A 垃圾......

另一种方式:

创建一个默认的私有Actor。让 B 成为 A 的朋友。但这听起来很老套和丑陋.. 处理这种情况的最佳方法是什么?我真的很想避免为 A 创建一个默认构造函数。

提前致谢。

【问题讨论】:

  • 不要写自定义的移动ctor,使用默认的。
  • 你根本不应该在复制构造函数中使用*this = std::move(other);
  • @n.m.我也是这么想的,但是他们想将int 数据成员设置为0
  • n.m:我需要一个默认移动,因为析构函数检查: if(data_) deletesomething(); data 实际上不是一个 int,它是一种资源。 juanchopanza:为什么不呢?该建议来自微软本身:“如果您为您的类提供移动构造函数和移动赋值运算符,则可以通过编写移动构造函数来调用移动赋值运算符来消除冗余代码。”来源:msdn.microsoft.com/en-us/library/dd293665.aspx
  • @sap 我和Hinnant on this one在一起。

标签: c++


【解决方案1】:

解决方案是这样做:

class A {
  int data_ = 0;

public:
    A(const A& other) = delete;
    A& operator=(const A& other) = delete;

    A(int data) : data_(data) {}
    ~A() {}

    A(A&& other) : data_(other.data_) { other.data_ = 0; }
    A& operator=(A&& other) {
        if (this != &other) {
            data_ = other.data_;
            other.data_ = 0;
        }
        return *this;
    }
};

class B {
    A a;

public:
    B(const B& other) = delete;
    B& operator=(const B& other) = delete;

    B(int data) : a(data) {}
    ~B() {}

    B(B&& other) : a(std::move(a)) {  }
    B& operator=(B&& other) {
        if (this != &other) {
            a = std::move(other.a);
        }
        return *this;
    }
};

虽然,由于 A 只包含一个 int,它不会导致比副本更好的性能...

【讨论】:

  • 谢谢,这就是我最终要做的,我这样做不是因为性能,而是因为我希望能够移动资源而不是复制它。如果我在所有这些类的析构函数中显示类似的东西,那就更有意义了: if(id_) delete resource_;这样我仍然可以在容器中使用它们(通过移动),同时防止每次副本到达析构函数时复制和删除多个资源。
【解决方案2】:

由于您的类B 中声明了A 的对象,因此您需要在构造B 时创建它。 C++中的普通对象不能没有值,也不能被创建(因为没有默认构造函数)。

要解决您的问题,请创建一个指向 a 的指针,该指针可以具有值 0,因此不需要在您的构造函数中创建它。更改此行:

A a;

进入这个:

private:
    A *a = 0;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-22
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    相关资源
    最近更新 更多