我有一个名为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
(这是有原因的,不应复制此类的对象)。但是我很困惑为什么复制构造函数被调用,因为我传递了一个共享指针,以及如何避免这种情况。
答案 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_shared
,classA
通过调用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}}