C ++拷贝构造函数:尝试引用已删除的函数

时间:2018-04-12 23:29:09

标签: c++ shared-ptr copy-constructor

我有一个名为classA的课程,如下所示:

class classA {
    private:        
        char* data; 
    public:
        classA(const classA&) = delete;
        ~classA();      
    };

~classA()
    {
        delete[] data;
    }

在另一个课程中,我们称之为classB,我作为成员指向classA的共享指针:

class classB
    {
    private:
        std::shared_ptr<classA> ptrA;
    public: 
        classB(std::shared_ptr<classA>);
    };

classB(std::shared_ptr<classA> sp) : ptrA(sp)
    {}

这是我实例化classB

的方法
classA ca;
classB cb(std::make_shared<classA>(ca));

这给了我以下错误:

  

尝试引用已删除的功能

显然,我正在尝试引用复制构造函数,我将其定义为deleted(这是有原因的,不应复制此类的对象)。但是我很困惑为什么复制构造函数被调用,因为我传递了一个共享指针,以及如何避免这种情况。

2 个答案:

答案 0 :(得分:7)

您正在调用复制构造函数来尝试创建共享指针。

std::make_shared<classA>(ca)
                         ^^ constructs the classA using these parameters

您可以调用make_shared<classA>()来创建指向默认构造的classA的共享指针。或者选择另一个构造函数。

答案 1 :(得分:2)

这个例子可以简化很多。

#include <memory>

class classA {
 public:
  classA(const classA&) = delete;
  classA() = default;
};


int main() {
  classA ca; // note, no ()
  auto sp = std::make_shared<classA>(ca); // problem.
  auto sp2 = std::make_shared<classA>();  // this does what you want
}

您正在将ca作为参数传递给std::make_sharedclassA通过调用classA::classA来构造make_shared,其中包含您传递给make_shared的任何参数。< / p>

如果您考虑如何实施template <typename Cls, typename... Args> std::shared_ptr<Cls> MakeShared(Args&&... args) { //this is where the copying happens return std::shared_ptr<Cls>{new Cls{std::forward<Args>(args)...}}; } int main() { classA ca; auto sp = MakeShared<classA>(ca); auto sp2 = MakeShared<classA>(); } ,这可能会更加明显。

ca

您将MakeShared传递给new Cls(...)...然后调用MakeShared,其中classA是您传递给forward的任何内容,在这种情况下是另一个{{} 1}}对象。

如果上述内容过于密集(可能您不习惯MakeShared或可变参数模板),请考虑template <typename Cls, typename Arg> std::shared_ptr<Cls> MakeShared(const Arg& arg) { // copy here ----+ // v return std::shared_ptr<Cls>{new Cls{arg}}; } int main() { classA ca; auto sp = MakeShared<classA>(ca); } 的简化版本,它可以为您的问题案例做同样的事情

{{1}}