Ответ
std::make_shared — это функция-хелпер для создания std::shared_ptr. Её ключевое отличие от прямого использования конструктора shared_ptr — в оптимизации выделения памяти.
Плюсы:
- Безопасность при исключениях: Выделение памяти под объект и под control block (счётчик ссылок) происходит атомарно. Это исключает утечку памяти, если, например,
newуспешен, но конструкторshared_ptrбросает исключение. - Эффективность: Обычно требует одного выделения памяти (heap allocation) для размещения и объекта, и control block вместе. Это уменьшает фрагментацию и накладные расходы.
- Локализация данных: Объект и control block находятся рядом в памяти, что может улучшить производительность кэша процессора.
- Удобство: Более лаконичный синтаксис.
Минусы:
- Невозможность использовать кастомный аллокатор:
make_sharedвсегда используетoperator new. Для использования аллокатора нужно применятьallocate_shared. - Невозможность передать пользовательский deleter.
- Продлённое время жизни памяти объекта: Память, занятая объектом, освобождается только тогда, когда уничтожены все
shared_ptrиweak_ptr, ссылающиеся на него, так как объект и control block находятся в одном блоке памяти. При использованииshared_ptr(new T)память под объект освобождается сразу при уничтожении последнегоshared_ptr, даже если живутweak_ptr.
Пример:
// Хорошо: одно выделение, безопасно при исключениях.
auto sp1 = std::make_shared<MyClass>(arg1, arg2);
// Потенциально проблемно: два выделения (new + control block).
// Если 'new MyClass' успешен, но выделение под control block бросит bad_alloc,
// память под MyClass утечёт.
std::shared_ptr<MyClass> sp2(new MyClass(arg1, arg2));