当我想要多态行为时,我经常发现自己在 C++ 中使用唯一指针。我通常实现纯抽象类,如下所示:
class A {
public:
virtual A* clone() const = 0; // returns a pointer to a deep copy of A
// other methods go here
};
当我想用自己的 A 实例修饰另一个类时, clone 方法会派上用场,例如:#include <memory>
class B {
private:
std::unique_ptr<A> a_ptr;
public:
// ctor
B(const A& a) {
a_ptr = std::unique_ptr<A>(a.clone());
//...
}
// copy ctor
B(const B& other) : B(*other.a_ptr) {}
};
我总是最终在 B 中实现复制构造函数以避免编译器错误(MSVC 给出了关于尝试引用已删除函数的模糊消息),由于唯一指针,这是完全合理的。我的问题可以总结如下:在实践中,每当我觉得需要实现默认函数时,我通常会在其他三个函数旁边实现一个移动构造函数;我通常使用 copy-and-swap-idiom(根据 GManNickG's answer in this thread )。我认为这不会改变任何事情,但也许我错了!
非常感谢!
最佳答案
首先,我认为你的克隆函数的签名可能是
virtual std::unique_ptr<A> clone() = 0;
因为您想要
A
实例的深层拷贝和 B
中的独占所有权。其次,当您希望它是可复制的时,您确实必须为您的类定义一个复制构造函数。赋值运算符也是如此。这是因为 std::unique_ptr
是一种仅移动类型,这阻碍了编译器生成默认实现。不需要其他特殊成员函数,尽管它们可能有意义。编译器不会为您生成移动构造函数和移动赋值运算符(当您发布自己的复制/赋值函数时),但在您的情况下,您可以轻松地对其进行
= default;
。析构函数同样可以用 = default;
定义,这与 core guidelines 一致。请注意,通过
= default
定义析构函数应该在翻译单元中完成,因为 std::unique_ptr
要求在释放其资源时知道完整类型。是否需要默认构造函数完全取决于您想如何使用
B
类。关于c++ - 唯一指针和 3 的规则,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51322684/