Зачем инициализировать 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, а затем набрать много инициализации справа от =..

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


person Yanko    schedule 27.05.2013    source источник
comment
Эм, почему? Потому что вы хотите первое, а не второе? Они не эквивалентны. (Проверьте decltype(pb))   -  person R. Martinho Fernandes    schedule 27.05.2013
comment
здесь ясно одно: если у вас есть производный smart_pointer, вы не можете легко привести его к базе. потому что в отличие от базы *x; и производное *y; в иерархии типов нет связи.   -  person Alexander Oh    schedule 27.05.2013
comment
Просто интересно, будет ли unique_ptr<base> pb = make_unique<derived>(); проще? То, что auto существует, не означает, что мы должны его использовать.   -  person FredericS    schedule 27.05.2013
comment
@FredericS: это было бы немного короче, более знакомо людям, не привыкшим к C++11, и менее явным, поскольку включает неявное преобразование. Делает ли это проще или нет, это эстетическое суждение.   -  person Mike Seymour    schedule 27.05.2013
comment
Мне все еще нравится auto pb = unique_ptr<base>(new derived()); для ясности.   -  person Sander De Dycker    schedule 27.05.2013
comment
@SanderDeDycker даже лучше с uniform-init: {}   -  person emesx    schedule 27.05.2013


Ответы (3)


Дело в том, что первый вариант превращает 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"
// ...
person Andy Prowl    schedule 27.05.2013
comment
@AndyProwl прячет улики, не так ли? - person Bartek Banachewicz; 27.05.2013
comment
@BartekBanachewicz: Я? Я бы никогда этого не сделал! (...сколько стоит удаление вашего комментария?) ;) - person Andy Prowl; 27.05.2013
comment
С++ сейчас такой уродливый. Я хочу вернуть свои new/delete! - person Lightness Races in Orbit; 27.05.2013
comment
@BoundaryImposition Их никто не забрал. У вас просто есть альтернативы сейчас. - person tambre; 21.04.2017

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

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

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

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

person Mike Seymour    schedule 27.05.2013
comment
+1 за ссылку на комментарий Херба (и ваш хороший ответ тоже :) - person emesx; 27.05.2013

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 в статье, на которую есть ссылка, приводит к тому, что кто-то отвечает именно на этот вопрос.

person Yakk - Adam Nevraumont    schedule 27.05.2013