← Назад к вопросам

Какие плюсы и минусы make_shared?

2.3 Middle🔥 131 комментариев
#Умные указатели и управление памятью

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Плюсы и минусы make_shared

make_shared — это функция из <memory>, которая создаёт объект и оборачивает его в std::shared_ptr одной операцией. Вот ключевые преимущества и недостатки.

Плюсы make_shared

1. Единая оптимизация выделения памяти При использовании make_shared управляемый блок (control block) и данные объекта выделяются одним сплошным блоком памяти. Это значительно эффективнее обычного конструктора shared_ptr:

// ✅ Одна операция выделения, оптимально
auto ptr1 = std::make_shared<MyClass>(arg1, arg2);

// ❌ Две операции выделения
auto ptr2 = std::shared_ptr<MyClass>(new MyClass(arg1, arg2));

2. Безопасность исключений (exception safety) make_shared гарантирует отсутствие утечек памяти при исключениях на этапе создания:

// ❌ Опасно: если func2() выкидит исключение, память утечёт
func(std::shared_ptr<MyClass>(new MyClass()), func2());

// ✅ Безопасно
func(std::make_shared<MyClass>(), func2());

3. Более компактный код Синтаксис чище и понятнее, нет явного new.

4. Лучшая локальность данных Управляемый блок и объект в одной памяти → меньше кеш-промахов, лучше производительность при обходе структур данных.

Минусы make_shared

1. Невозможность пользовательского удаления (deleter) make_shared использует стандартный удаления. Если нужен кастомный deleter, придётся использовать обычный конструктор:

auto deleter = [](MyClass* p) { 
    std::cout << "Удаляю объект" << std::endl; 
    delete p; 
};

// ❌ make_shared не поддерживает deleter
// auto ptr = std::make_shared<MyClass>(deleter);  // ОШИБКА

// ✅ Только через конструктор
auto ptr = std::shared_ptr<MyClass>(new MyClass(), deleter);

2. Сложнее с массивами (до C++20) В C++20 появился make_shared для массивов, но раньше это было невозможно:

// C++20 и позже
auto arr = std::make_shared<int[]>(100);

// Раньше только так
auto arr = std::shared_ptr<int[]>(new int[100]);

3. Отсроченное удаление объекта Пока существует хотя бы одна копия shared_ptr, объект не будет удалён, даже если больше никто на него не ссылается (out of scope). Иногда это нежелательно для больших объектов:

auto ptr = std::make_shared<LargeClass>();
{
    auto copy = ptr;  // Ещё одна ссылка
    // copy выходит из scope, но объект не удалён!
}
// Объект удалится только здесь, когда удалится последняя копия

4. Проблема со слабыми ссылками (weak_ptr) Если объект имеет циклические ссылки через weak_ptr, и используется make_shared, memory может быть освобождена только когда удалятся все weak_ptr:

auto shared = std::make_shared<Node>();
auto weak = std::weak_ptr<Node>(shared);
// Даже после обнуления shared, память может оставаться, 
// если weak_ptr всё ещё существует

5. Невозможность контролировать выравнивание (до C++20) Кастомное выравнивание не поддерживалось в старых стандартах.

Когда использовать что

Используй make_shared:

  • Стандартное удаление достаточно
  • Нужна производительность и безопасность исключений
  • Работаешь с единичными объектами, не с массивами

Используй обычный конструктор shared_ptr:

  • Нужен кастомный deleter
  • Нужны функции вроде get_deleter()
  • Работаешь с массивами (до C++20)
  • Есть специфические требования к памяти
Какие плюсы и минусы make_shared? | PrepBro