Home > Mobile >  Copy constructor difference for std::unique_ptr
Copy constructor difference for std::unique_ptr

Time:12-04

If my understanding is correct, the following declarations should both call the copy constructor of T which takes type of x as a parameter.

T t = x;
T t(x);

But when I do the same for std::unique_ptr<int> I get an error with the first declaration, while the second compiles and does what is expected.

std::unique_ptr<int> x = new int();
std::unique_ptr<int> x (new int());

Is there a difference in the two syntax for calling the copy constructor?

CodePudding user response:

Constructor of std::unique_ptr<> is explicit, which means, you need to write it in the first case:

std::unique_ptr<int> x = std::unique_ptr<int>(new int());
// or
auto x = std::unique_ptr<int>(new int());
// or make_unique()

CodePudding user response:

std::unique_ptr::unique_ptr( pointer p ) is an explicit constructor, so that form of initialization is not allowed. Initializing with = always requires a converting-constructor for implicit conversions.

CodePudding user response:

Yes, there is a difference in the two syntax for calling the copy constructor for std::unique_ptr. The first syntax, T t = x;, is called copy initialization. It calls the copy constructor of std::unique_ptr if it exists, but if the copy constructor is deleted or inaccessible (as is the case with std::unique_ptr), then the compiler will instead try to use the move constructor of std::unique_ptr. However, std::unique_ptr doesn't have a move constructor, so the compiler will throw an error.

On the other hand, the second syntax, T t(x);, is called direct initialization. It only calls the copy constructor of std::unique_ptr, and will not try to use the move constructor if the copy constructor is deleted or inaccessible. Since std::unique_ptr doesn't have a copy constructor, this code will also throw an error.

In general, it is best to avoid using copy initialization with std::unique_ptr to avoid this issue. Instead, you should use direct initialization, or use one of the other ways to initialize a std::unique_ptr, such as using the make_unique function.

For example:

std::unique_ptr<int> x = std::make_unique<int>();
std::unique_ptr<int> y(std::make_unique<int>());

Both of these declarations will properly initialize x and y with a new int object using the make_unique function, without trying to use the copy or move constructor of std::unique_ptr.

  • Related