std::unique_ptr и оператор '='

Может кто-нибудь объяснить разницу:

std::unique_ptr<int> item1(new int); 
std::unique_ptr<int> item2 = item1;

Здесь вторая строчка вызывает ошибку, но если добавить функцию:

std::unique_ptr<int> createItem()
{
    return std::make_unique<int>();
}

и вызвать

std::unique_ptr<int> item2 = createItem();

То все будет нормально. Но почему? Разве в двух случаях не вызывается один и тот же конструктор копирования?


Ответы (1 шт):

Автор решения: αλεχολυτ

Для std::unique_ptr запрещено копирование. Разрешение только перемещение. При выполнении варианта с функцией и присваивание результата происходит перемещение возвращаемого результата функции в указатель. Поэтому код работает.

Чтобы работал и в первом случае можно добавить std::move, который приведёт аргумент к rvalue и позволит выполнить перемещение, а не копирование.

std::unique_ptr<int> item2 = std::move(item1);

В этом случае значение из item1 переходит в item2, т.е. item1 перестаёт владеть данными и становится пустым. Однако здесь вызывается не operator=, а происходит вызов перемещающего конструктора, т.к. объект item2 только создаётся. Если бы запись выглядела так:

item2 = std::move(item1);

При условии, что item2 создан где-то ранее, то тогда это уже было бы вызовом перемещающего operator=.

→ Ссылка