包含智能指针的类的复制构造函数

Copy constructor of a class containing a smart pointer

提问人:Tyler D 提问时间:9/25/2020 最后编辑:Tyler D 更新时间:9/25/2020 访问量:244

问:

在下面的示例中,我们有一个类,其中包含一个对象,该对象为我们处理所有内存(三法则)。ClassBridge

class Base {
public:
    Base() {};
    virtual Base* clone() const = 0;
    virtual ~Base() {};
};

class Derived : public Base {
public:
    Derived() {};
    virtual Base* clone() const {
        return new Derived(*this);
    }
    virtual ~Derived() {}
};

class Bridge {
public:
    Bridge(const Bridge& bridge_) {
        base = bridge_.base->clone();
    }
    Bridge(const Base& base_) {
        base = base_.clone();
    }
    ~Bridge() { delete base; }
    
    Bridge& operator=(const Bridge& assignFrom) {
        if(this != &assignFrom) {
            delete base;
            base = assignFrom.base->clone();
        }
        return *this;
    }
private:
    Base *base;
};

class Class {
public:
    Class(const Bridge& bridge_) : bridge(bridge_) {};
private:
    Bridge bridge;
};

int main()
{
    Derived derived;
    Class c(derived);
    Class c1(c);  
}

现在,我刚刚了解了智能指针,并尝试使用 .据我了解,我们基本上不需要自己实现 3 规则,因为智能指针已经包含它。为了测试这一点,我制作了以下示例:unique_ptr

class BaseSMRT {
public:
    BaseSMRT() {};
    virtual std::unique_ptr<BaseSMRT> clone() const = 0;
    virtual ~BaseSMRT() {};
};

class DerivedSMRT : public BaseSMRT {
public:
    DerivedSMRT() {};
    virtual std::unique_ptr<BaseSMRT> clone() const {
        return std::make_unique<DerivedSMRT>(*this);
    }
    virtual ~DerivedSMRT() {}
};

class ClassSMRT {
public:
    ClassSMRT(const BaseSMRT& base) {
        ptr = base.clone();
    };
private:
    std::unique_ptr<BaseSMRT> ptr;
};

int main()
{
    DerivedSMRT derivedSMRT;
    ClassSMRT cSMRT(derivedSMRT);
    ClassSMRT cSMRT2(cSMRT); // error: Call to implicitly-deleted copy constructor of 'ClassSMRT'
}

正如您在上面的示例中看到的,通过复制构造函数进行初始化不起作用,并给了我上述错误。cSMRT2cSMRT

我不明白:为什么我可以像这样调用默认复制构造函数,但不能调用默认复制构造函数?ClassClass c1(c);ClassSMRTClassSMRT cSMRT2(cSMRT);

这表明,当我们使用 .unique_ptr

C++ OOP 唯一 PTR 三法则

评论

0赞 molbdnilo 9/25/2020
请比“不起作用”更具体。
1赞 Evg 9/25/2020
std::unique_ptr是不可复制的。它没有复制构造函数来复制由 保存的对象。unique_ptr
1赞 Evg 9/25/2020
因为它是 5 的规则,但复制操作被删除。如果要复制对象,则应自行完成。智能指针制作这样的副本在语义上是错误的——毕竟,它只是一个指针。unique_ptr
1赞 molbdnilo 9/25/2020
我发现,不要把它看作一个指针,而是把它看作一个独特的对象——它不能被复制,它只能被移动。unique_ptr
1赞 Alan Birtles 9/25/2020
智能指针可以防止你的程序在你违反 3/5 规则时意外出错,你仍然可能需要实现它们才能获得你想要的行为

答:

2赞 Caleth 9/25/2020 #1

unique_ptr旨在阻止意外复制。您希望在复制时隐式克隆多态类型。 不(直接)适合您的用途。unique_ptr

我建议重命名Bridge

template </*Cloneable*/ typename T>
class clone_ptr {
public:
    clone_ptr(const T& base_) 
      : base(base_.clone()) {}
    clone_ptr(const clone_ptr& other)
      : base(other.base->clone()) {}
    clone_ptr(clone_ptr&& other) = default;
    
    clone_ptr& operator=(clone_ptr other) {
        base = std::move(other.base);
        return *this;
    }
private:
    std::unique_ptr<T> base;
};

评论

0赞 Evg 9/25/2020
不应该通过const-ref吗?operator=clone_ptr
1赞 Caleth 9/25/2020
@Evg按值获取包括移动和复制,如果我按照我的意图实现它。我责怪缺乏咖啡自动取款机
0赞 Evg 9/25/2020
通过移动来获取价值是一个很好的解决方案。