调用隐式删除的复制构造函数

Call to implicitly deleted copy constructor

本文关键字:复制 构造函数 删除 调用      更新时间:2023-10-16

我有以下设置:

class MyClass {
public:
static MyClass Clone(const MyClass& other) { 
return MyClass(other, 10);
}
static MyClass CreateNormal(int x, int y) {
return MyClass(int x, int y);
}
// There are a few more factory functions.
private:
// Constructor 1
MyClass(int x, int y) : b_(x, y) {}
// Constructor 2
MyClass(const MyClass& other, int c) : b_(other.b_, c) {}
// And a lot more constructors.

// NotMyClass has its copy constructor deleted.
NotMyClass b_;
}
int main() {
MyClass A(1,2);
MyClass B = MyClass::Clone(A); // ERROR
}

有没有办法在不修改NotMyClass的情况下解决这个问题? 发生此错误的原因是隐式删除了MyClass的复制构造函数。有没有办法使用 std::Move(( 来解决这个问题?

我无法删除工厂函数,因为实际类有许多构造函数,并且需要工厂函数才能清晰和理解。

假设 c++11 标准可用,则可以延长工厂方法返回的右值引用的生存期,而不是构造一个新对象,如下所示:

MyClass   A(1, 2);
MyClass&& B = MyClass::Clone(A);

补遗: 正如 patatahooligan 在下面的评论中指出的那样,您的MyClass::Clone版本本身中可能存在复制构造函数调用。这可以/需要重写为

MyClass MyClass::Clone(const MyClass& other) {
return {other, 10};
}

一旦 C++17 带有强制性复制省略,所有这些都将完全没有必要,所以你可以期待这一点。


在 C++03 中,尽管解决方案更长并且需要更多的代码,但仍有可能实现预期的结果。我提供两种选择:

与其创建一组静态方法,我建议使用 tag-dispatch 来表示不同的构造函数含义。这通过使用具有明确名称但不保存数据的类型参数重载构造函数来工作。

struct clone_tag {};
class MyClass {
public:
MyClass(int x, int y) : b_(x, y) {}
MyClass(const MyClass& self, clone_tag) : b_(self.b_, 10) {}
private:
NotMyClass b_;
};
int main() {
MyClass   A(1, 2);
MyClass   B(A, clone_tag());
}

或者这甚至可以达到真正的工厂模式,其中建造工厂和物体的最终建筑是分开的。这显然需要更多时间来设置,但可以提高代码质量,具体取决于不同构造函数路径的实际数量。

class MyClass {
public:
struct Clone {
Clone(const MyClass& self) : self(self) {}
const MyClass& self;
};
struct Init {
Init(int x, int y) : x(x), y(y) {}
int x, y;
};
MyClass(Init i) : b_(i.x, i.y) {}
MyClass(Clone c) : b_(c.self.b_ , 10) {}
private:
MyClass(const MyClass& other, int c) : b_(other.b_, c) {}
NotMyClass b_;
};

int main() {
MyClass   A = MyClass::Init(1, 2);
MyClass   B = MyClass::Clone(A);
}

再三考虑,我意识到给出三种不同的选择可能会比不太精确的简短答案引起更多的混乱。因此,我试图按所需的重构工作的顺序列出它们,尽管这只是对真实代码库的猜测。