EDIT: I understand unique_ptr is non-copyable and can be only moved. i do not understand what happens with the initialization list.
Why unique_ptr in member initialization list can work as in the code snipt?
#include <memory>
class MyObject
{
public:
MyObject() : ptr(new int) // this works.
MyObject() : ptr(std::unique_ptr<int>(new int))
// i found this in many examples. but why this also work?
// i think this is using copy constructor as the bottom.
{
}
MyObject(MyObject&& other) : ptr(std::move(other.ptr))
{
}
MyObject& operator=(MyObject&& other)
{
ptr = std::move(other.ptr);
return *this;
}
private:
std::unique_ptr<int> ptr;
};
int main() {
MyObject o;
std::unique_ptr<int> ptr (new int);
// compile error, of course, since copy constructor is not allowed.
// but what is happening with member initialization list in above?
std::unique_ptr<int> ptr2(ptr);
}
In your example, std::unique_ptr<int>(new int)
is an rvalue, so the move-constructor of ptr
is used.
The second time (in main
), std::unique_ptr<int> ptr2(ptr)
doesn't work because ptr
is an lvalue, and cannot be moved directly (you can use std::move
).
This is to do with named and unnamed objects.
When you do this:
std::unique_ptr<int> ptr(new int);
// ^^^--- name is 'ptr'
But when you do this:
std::unique_ptr<int>(new int);
// ^--where is the name??
If an object is created without a name it is called a temporary or an r-value and the compiler has different rules for r-values than it does for named objects or l-values.
Named objects (l-values) can only be copied to another object but unnamed objects (r-values) can either be copied or moved.
In your example you use a std::unique_ptr
. These objects can only be moved because they have had their copy semantics disabled. This is why your compiler is giving an error when you try to copy one:
std::unique_ptr<int> ptr (new int);
// compile error, copy constructor delete
std::unique_ptr<int> ptr2(ptr); // copy is disabled!!
Here ptr
is a named object so it can only be copied but its copy semantics are disabled so the whole operation is illegal.
BUT when you do a similar thing with an unnamed object like this:
MyObject() : ptr(std::unique_ptr<int>(new int))
^--- look no name!!!
Then the compiler can either copy or move and it always tries to move before trying to copy.
The std::unique_ptr
is fully move complaint so the compiler has no complaints.
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