Зачем инициализировать unique_ptr с помощью вызова make_unique?

Взято из: http://herbsutter.com/2013/05/22/gotw-5-solution-overriding-virtual-functions/

Почему мы должны писать:

auto pb = unique_ptr<base>{ make_unique<derived>() };

Вместо просто:

auto pb = make_unique<derived>();

Мое единственное предположение, что если мы хотим autoнам нужно помочь вывести правильный тип (base Вот).

Если так, то для меня это было бы действительно сомнительным достоинством .. набрать auto а затем введите много инициализации на правой стороне = ..

Что мне не хватает?

6

Решение

Ну, дело в том, что первый вариант делает pb unique_ptr<base>в то время как второй вариант делает pb unique_ptr<derived>, Правильно ли оба в вашей ситуации или нет, зависит от того, что вы должны делать с pb — но определенно эти два не эквивалентны.

Если соответствующая часть вашей программы должна работать с unique_ptr<base> (возможно, потому что позже вы позволите ему указать на случай разные производный класс), то второе решение просто нежизнеспособно.

Например:

auto pb = unique_ptr<base>{ make_unique<derived>() };
// ...
pb = make_unique<derived2>(); // This is OK
// ...

В то время как:

auto pb = make_unique<derived>();
// ...
pb = make_unique<derived2>(); // ERROR! "derived2" does not derive from "derived"// ...
10

Другие решения

Мое единственное предположение, что если мы хотим auto, нам нужно помочь ему определить правильный тип (база здесь).

Это совершенно верно. Без преобразования, pb будет указатель на derived что может быть не то, что вы хотите. Например, вы не можете переназначить его на base или другой объект производного класса.

Если так, то для меня это было бы действительно сомнительной заслугой ..

Я склонен согласиться. Автор отмечает в комментарий что он сделал это, потому что ему нравится максимально использовать дедукцию типов с явными преобразованиями, где это необходимо. Время покажет, станет ли этот стиль обычным делом.

6

auto pb = unique_ptr<base>{ make_unique<derived>() };

вышеизложенное создает unique_ptr<base> который содержит derived,

auto pb = make_unique<derived>();

вышеизложенное создает unique_ptr<derived> который содержит derived,

Хотя замена 2-го на 1-й может быть приемлемой, они на самом деле делают разные вещи.

В сторону, в поисках make_unique в связанной статье приводятся ответы на этот самый вопрос.

4