Reputation: 1299
I need to write a copy constructor that also transfer the ownership of a unique_ptr member of the object being copied. The situation is as follows:
class C{
// C class stuff
};
class A{
public:
public A();
public A(const A& a);
private:
std::unique_ptr<C> c_;
}
class B{
public:
B(const A& b) : a_(a){}
private:
A a_;
};
How should I implement the copy constructor for A
?
Upvotes: 6
Views: 5209
Reputation: 38919
Obviously you cannot just do an assignment of std::unique_ptr
s as their assignment operator is deleted. This is intentional to force the programmer to define the behavior he wants.
c_
, invalidating the original item.c_
, retaining the original items validity.c_
so that both the new and original items reference the same object.In case 1 what you're looking for is a move constructor, and the default move constructor will work fine. So you don't need to write any code, you can just do:
A temp;
A foo(std::move(temp));
Note that temp
is invalid after it is moved.
In case 2 you'll need to add a custom copy constructor to A
to create a copy of the original's c_
:
A(const A& a):c_(new C(*(a.c_))){}
After defining this in A
you can do:
A foo(A());
Note that this depends upon C
's copy constructor being functional.
In case 3 you'll need to fundamentally change A
from using a std::unique_ptr
to using a std::shared_ptr
, so the definition of c_
would become:
std::shared_ptr<C> c_;
Your construction of c_
would be identical to what you're already using for the std::unique_ptr
version of c_
. So just using the default implementations you could do:
A foo;
A bar(foo);
And now foo
and bar
point to the same C
object, and share ownership of it. This shared object will not be deleted until all shared_ptr
s referencing it have been deleted.
Upvotes: 4
Reputation: 145279
Technically, to
” write a copy constructor that also transfer the ownership of a unique_ptr member of the object being copied
you can just do this:
class Bad
{
private:
unique_ptr<int> p_;
public:
Bad(): p_( new int(666) ) {}
Bad( Bad& other )
: p_( move( other.p_ ) )
{}
};
Because a copy constructor can have also this signature, plus two more, in addition to the more conventional Bad( const Bad& )
.
I named that class Bad
because it's really bad, it just does not make sense to do this thing except as sabotage of someone else's code.
Instead of a copy constructor that doesn't copy,
implement a move constructor that moves, or
implement an ordinary copy constructor that copies, or
change the class design to e.g. shared ownership.
Upvotes: 3
Reputation: 1879
Your intent or approach is wrong, I guess.
The copy-constructor is meant to create a copy of the argument, but since unique_ptr
maintains sole ownership one cannot make a copy of it. You could in fact make the unique_ptr member mutable
and then move the resource it points to in the copy-constructor but that would be absolutely insane (this is what std::auto_ptr
does and this is why it's deprecated).
Therefore either you need to:
unique_ptr
to shared_ptr
, but only if C is actually meant to be sharedThere's also a third option, which is to make a copy of the object pointed to by the unique_ptr in A's copy-constructor, i.e.:
A::A(const A& a) : c_(std::unique_ptr<C>(a.c_ ? new C(*a.c_) : nullptr)) {
}
Upvotes: 6