I have a class called classA
, something like this:
class classA {
private:
char* data;
public:
classA(const classA&) = delete;
~classA();
};
~classA()
{
delete[] data;
}
In another class, let's call it classB
, I have as a member a shared pointer to classA
:
class classB
{
private:
std::shared_ptr<classA> ptrA;
public:
classB(std::shared_ptr<classA>);
};
classB(std::shared_ptr<classA> sp) : ptrA(sp)
{}
This is how I instantiate my classB
:
classA ca;
classB cb(std::make_shared<classA>(ca));
This gives me the following error:
attempting to reference a deleted function
Obviously, I am trying to reference the copy constructor, which I defined as deleted
(there is a reason for this, objects of this class shouldn't be copied). But I am confused as to why the copy constructor is called since I am passing a shared pointer, and how to avoid this.
You're calling the copy constructor trying to make the shared pointer.
std::make_shared<classA>(ca)
^^ constructs the classA using these parameters
You can call make_shared<classA>()
to create a shared pointer to a default constructed classA
. Or chose another constructor.
This example can be simplified quite a bit.
#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
}
You are passing ca
as an argument to std::make_shared
, which constructs a classA
by calling classA::classA
with whatever arguments that you passed to make_shared
.
This might be more obvious if you consider how a make_shared
might be implemented.
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>();
}
You pass ca
to MakeShared
, which then calls new Cls(...)
where the ...
is whatever you passed to MakeShared
, in this case, another classA
object.
If the above is too dense (maybe you aren't used to forward
or variadic templates), then consider this simplified version of MakeShared
which does the same thing for your problem case
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With