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

Почему рекомендуют использовать std::make_shared

1️⃣ Как кратко ответить

Использование std::make_shared рекомендуется, потому что оно более эффективно и безопасно, чем прямое использование конструктора std::shared_ptr. Оно выполняет единую аллокацию памяти для объекта и управляющего блока, что уменьшает накладные расходы и снижает вероятность ошибок, связанных с управлением памятью.

2️⃣ Подробное объяснение темы

std::make_shared — это функция, которая создает объект и возвращает std::shared_ptr, указывающий на этот объект. Она была введена в C++11 и является предпочтительным способом создания объектов, управляемых std::shared_ptr, по нескольким причинам.

Эффективность

Когда вы используете std::make_shared, память для самого объекта и управляющего блока (который хранит счетчик ссылок и другую служебную информацию) выделяется за один вызов аллокатора. Это уменьшает количество операций выделения памяти, что может значительно повысить производительность, особенно в системах с ограниченными ресурсами.

Пример:

#include <memory>
#include <iostream>
​
class MyClass {
public:
    MyClass() {
        std::cout << "MyClass constructor\n";
    }
    ~MyClass() {
        std::cout << "MyClass destructor\n";
    }
};
​
int main() {
    // Создание объекта с использованием std::make_shared
    std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>();
    return 0;
}
  • std::make_shared<MyClass>() создает объект MyClass и std::shared_ptr, указывающий на него, за одну операцию выделения памяти.

Безопасность

Использование std::make_shared снижает вероятность ошибок, связанных с управлением памятью. Например, если вы создаете объект с помощью new и затем передаете его в конструктор std::shared_ptr, существует риск утечки памяти, если произойдет исключение между этими двумя операциями.

Пример потенциальной проблемы:

#include <memory>
#include <iostream>
​
class MyClass {
public:
    MyClass() {
        std::cout << "MyClass constructor\n";
    }
    ~MyClass() {
        std::cout << "MyClass destructor\n";
    }
};
​
int main() {
    // Потенциально небезопасный способ создания shared_ptr
    MyClass* rawPtr = new MyClass();
    std::shared_ptr<MyClass> ptr(rawPtr);
    return 0;
}
  • Если между new MyClass() и std::shared_ptr<MyClass> ptr(rawPtr) произойдет исключение, объект MyClass не будет освобожден, что приведет к утечке памяти.

Применение

std::make_shared широко используется в современных C++ приложениях, где требуется управление временем жизни объектов. Это особенно полезно в многопоточных приложениях, где важно минимизировать накладные расходы на управление памятью и избегать ошибок, связанных с конкурентным доступом к ресурсам.

Заключение

Использование std::make_shared — это не только вопрос стиля, но и практическая необходимость для написания более эффективного и безопасного кода. Оно упрощает управление памятью и снижает вероятность ошибок, что делает его предпочтительным выбором для создания объектов, управляемых std::shared_ptr.

Тема: Умные указатели / Владение
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки