Copy constructor to transfer ownership of unique_ptr

I need to write a copy constructor that also transfers ownership of the unique_ptr instance 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 do I implement the copy constructor for A ?

+5
source share
3 answers

Your intention or approach is wrong, I think.

The copy constructor is designed to create a copy of the argument, but since unique_ptr supports sole ownership, it cannot be copied. In fact, you could make member_txt_cl_ mutable and then move the resource it points to in the copy constructor, but that would be completely insane (this is what std::auto_ptr does, and that is why it is deprecated).

Therefore you need to:

  • add the move constructor to A and B (+ remove the copy constructor)
  • switch from unique_ptr to shared_ptr , but only if C is actually intended to be shared.

There is also a third option, which is to make a copy of the object pointed to by unique_ptr in copy-constructor, i.e.

 A::A(const A& a) : c_(std::unique_ptr<C>(a.c_ ? new C(*a.c_) : nullptr)) { } 
+5
source

Obviously, you cannot just do the assignment std::unique_ptr , as their assignment operator is removed. This intentionally forces the programmer to determine what behavior he wants.

  • The new item gains ownership of c_ , the invalid source item.
  • The new element creates a copy of c_ , while maintaining the authenticity of the original elements.
  • The new element shares ownership of c_ so that both the new and original elements refer to the same object.

In case 1 , what you are looking for is a move constructor, and the default move constructor will work fine. Therefore, you do not need to write any code, you can just do:

 A temp; A foo(std::move(temp)); 

Note that temp not valid after moving it.

In case 2, you need to add your own copy constructor in A to create a copy of the original 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 on the C functional constructor.

In case 3, you need to fundamentally change A using std::unique_ptr to use std::shared_ptr , so the definition of c_ will be as follows:

 std::shared_ptr<C> c_; 

Your build of c_ will be identical to what you are already using for std::unique_ptr version of c_ . So, just using standard implementations you could do:

 A foo; A bar(foo); 

And now foo and bar point to the same C object and share its ownership. This shared object will not be deleted until all shared_ptr referencing it has been deleted.

+4
source

Technically,

" write a copy constructor that will also transfer ownership of the unique_ptr element 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_ ) ) {} }; 

Since the copy constructor may also have this signature, plus two more, in addition to the more conditional Bad( const Bad& ) .

I called this class Bad , because it is really bad, it just does not make sense to do this, except to sabotage other code.

Instead of a copy constructor that doesn't copy,

  • implement a roaming move constructor, or

  • implement a regular copy instance that copies, or

  • change class design for example. joint ownership.

+3
source

Source: https://habr.com/ru/post/1215602/


All Articles