Copy std :: unique_ptr value through dereference

I wrote the following code where I am trying to copy the value of a unique_ptr object to a structure.

 #include <iostream> #include <memory> using namespace std; struct S { S(int X = 0, int Y = 0):x(X), y(Y){} // S(const S&) {} // S& operator=(const S&) { return *this; } int x; int y; std::unique_ptr<S> ptr; }; int main() { S s; s.ptr = std::unique_ptr<S>(new S(1, 4)); S p = *s.ptr; // Copy the pointer value return 0; } 

An error appears in Visual C ++ 2012:

IntelliSense: no suitable custom conversion from "S" to "S" exists
IntelliSense: operator "=" does not match these operands Operand types: std :: unique_ptr> = std :: unique_ptr>
error C2248: 'std :: unique_ptr <_Ty> :: unique_ptr': cannot access the private member declared in the class 'std :: unique_ptr <_Ty>'

If I did not uncomment the lines where I tried to define the copy constructor and = operator. This eliminates compiler errors, but not IntelliSense errors. It compiles regardless of the IntelliSense errors displayed in the error list.

So why can't it use the default functions and compile with them? Am I copying the value correctly? How to define a copy constructor if needed?

+5
source share
4 answers

The copy constructor is implicitly generated, because you have a user-defined constructor, why your attempt to copy S fails.

But still unique_ptr are not unique_ptr , only movable, so you can use the move constructor for S :

 S(S&& other) : x(other.x), y(other.y), ptr(std::move(other.ptr)) { } 

And call him:

 S p = std::move(s); // Move s to p 

Live demo

+5
source

std::unique_ptr not a Copy constructor or Copy assignable.

The implicit copy assignment operator and constructor for S will be poorly formed and therefore an error message.

However, you can use S p = std::move(s); since std::unique_ptr is Move Constructible and Move Assignable,

+2
source

So why can't it use the default functions and compile with them?

As far as I understand, the idea of ​​the unique_ptr container is that it exclusively processes the life of its contents (a pointer to T ) until it is relieved of this responsibility (using the swap or reset methods) or effectively destroying its contents (when it itself is destroyed). The second important property of unique_ptr is that it must allow incomplete types for T (in order to support opaque pointers). This means that the contained value cannot be CopyConstructible. Because of this, unique_ptr itself cannot be allowed CopyConstructible.

Am I making a copy of the value right? How to define a copy constructor if needed?

If T ends with CopyConstructible, how you want to do this, you must process the copy manually by accessing the pointer, as you do this in main . Probably the copy constructor should do the same.

+2
source

Not a complete answer, just informative:

I highly recommend adding visibility to your experiment:

 std::ostream& operator<<(std::ostream& os, const S& s) { os << '{' << sx << ", " << sy << ", "; if (s.ptr != nullptr) os << s.ptr.get() << ':' << *s.ptr; else os << "nullptr"; return os << '}'; } 

Now you can say things like:

 cout << "s = " << s << '\n'; 

in several places in your experiment, and really get a good idea of ​​what happens after each step. This should help you analyze and continue to develop.

+2
source

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


All Articles