Ответ 1
Первый случай не выполняет двойное распределение, он выполняет два распределения, один для управляемого объекта и один для блока управления shared_ptr
.
Во втором случае cppreference имеет хорошее объяснение, почему std:: make_shared обычно выполняет только одно выделение памяти, которое он говорит (акцент мой вперед):
Эта функция обычно выделяет память для объекта T и для shared_ptr с единичным распределением памяти (это необязательное требование в стандарте). Напротив, декларация std:: shared_ptr p (новый T (Args...)) выполняет как минимум две памяти распределения, которые могут повлечь ненужные накладные расходы.
и в разделе std:: shared_ptr говорится:
Когда shared_ptr создается путем вызова std:: make_shared или std:: allocate_shared, память как для блока управления, так и для управляемый объект создается с одним распределением. Управляемый объект строится на месте в элементе данных блока управления. когда shared_ptr создается через один из конструкторов shared_ptr, управляемый объект, а блок управления должен быть выделен отдельно. В в этом случае блок управления сохраняет указатель на управляемый объект.
Это описание make_shared
соответствует стандарту С++ 11, который гласит в разделе 20.7.2.2.6
shared_ptr creation
template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); template<class T, class A, class... Args> shared_ptr<T> allocate_shared(const A& a, Args&&... args);
[...]
Примечания: Реализации должны выполнять не более одной памяти распределение. [Примечание. Это обеспечивает эффективность, эквивалентную интрузивный умный указатель. -end note]
[Примечание. Эти функции обычно выделяют больше памяти, чем sizeof (T), позволяющий создавать внутренние бухгалтерские структуры, такие как подсчет ссылок. -end note]
Herb Sutter имеет более подробное объяснение преимуществ использования make_shared
в GotW # 89 Решение: Smart Pointers и указывает на некоторые преимущества:
- Это сокращает накладные расходы на распределение
- Это улучшает локальность.
- Избегает явного нового.
- Предотвращает проблему безопасности исключений.
Помните, что при использовании std:: weak_ptr с использованием make_shared есть некоторые недостатки.