Преимущества использования std :: make_unique для нового оператора
Каковы преимущества использования std::make_unique
над new
оператором для инициализации std::unique_ptr
?
Другими словами, почему
std::unique_ptr<SomeObject> a = std::make_unique(SomeObject(...))
лучше, чем делать
std::unique_ptr<SomeObject> a = new SomeObject(...)
Я попытался найти много онлайн, и я знаю, что это хорошее правило, чтобы избежать new
оператора в современном C++, но я не уверен, какие преимущества в этом точном сценарии. Предотвращает ли это утечку памяти, которая может произойти? std::make_unique
ли делать std::make_unique
чем использовать new
?
Ответы
Ответ 1
преимущества
-
make_unique
учит пользователей "никогда не говорить new
/delete
и new[]
/delete[]
" без оговорок.
-
make_unique
два преимущества с make_shared
(исключая третье преимущество, повышенную эффективность). Во-первых, unique_ptr<LongTypeName> up(new LongTypeName(args))
должно упоминать LongTypeName
дважды, в то время как auto up = make_unique<LongTypeName>(args)
упоминает его один раз.
-
make_unique
предотвращает make_unique
неуказанного порядка оценки, вызванную выражениями типа foo(unique_ptr<X>(new X)
, unique_ptr<Y>(new Y))
. (Следуя совету "никогда не говорить new
", это проще, чем "никогда не говорить ничего new
, если только вы не сразу отдадите его на имя unique_ptr
").
-
make_unique
тщательно внедряется для обеспечения безопасности исключений и рекомендуется для прямого вызова конструкторов unique_ptr
.
Когда не используется make_unique
- Не используйте
make_unique
если вам нужен пользовательский отладчик или вы используете необработанный указатель из другого места.
источники
- Предложение
std::make_unique
. - Herb Sutter GotW # 89 Решение: Умные указатели
Ответ 2
Разница в том, что std::make_unique
возвращает объект типа std::unique_ptr
а new
возвращает указатель на созданный объект. При сбоях в распределении памяти они будут бросать. Держись, это не так просто. Читайте дальше.
Рассмотрим такую функцию ниже:
void func(ClassA* a, ClassB* b){
......
}
Когда вы делаете вызов как func(new A(), new B())
; Компилятор может выбрать оценку аргументов функции слева направо или в любом порядке, который он пожелает. Пусть предполагаемая оценка слева направо: что происходит, когда первое new
выражение успешно выполняется, но второе new
выражение бросает?
Настоящая опасность здесь заключается в том, когда вы поймаете такое исключение; Да, вы могли поймать исключение, вызванное new B()
, и возобновить нормальное выполнение, но new A()
уже преуспел, и его память будет пропущена. Никто не убирает его... * рыдает...
Но с make_unique
вас не может быть утечки, потому что произойдет make_unique
стека (и деструктор ранее созданного объекта будет запущен). Следовательно, предпочтение make_unique
будет ограничивать вас безопасностью исключений. В этом случае std::make_unique
предоставляет "Базовую безопасность исключения", которую выделенная память и объект, созданные new
, никогда не будут потеряны, несмотря ни на что. Даже до конца времени... :-)
Вы должны прочитать Herb Sutter GoTW102