← Назад к вопросам
Как можно создать std::shared_ptr?
1.0 Junior🔥 111 комментариев
#Умные указатели и управление памятью
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Способы создания std::shared_ptr
std::shared_ptr — это умный указатель с подсчётом ссылок. Существует несколько способов его создания, каждый с разными гарантиями безопасности и производительности. Лучший способ — std::make_shared.
Способ 1: std::make_shared (РЕКОМЕНДУЕТСЯ)
Преимущества:
- ✅ Один heap allocation вместо двух
- ✅ Exception-safe при использовании в функциональных аргументах
- ✅ Лучшая кэширование
- ✅ Меньше фрагментации памяти
#include <memory>
class MyClass {
public:
MyClass(int x, const std::string& s) : value(x), name(s) {}
private:
int value;
std::string name;
};
int main() {
auto ptr = std::make_shared<MyClass>(42, "Hello");
ptr->getValue();
return 0;
}
Способ 2: new + конструктор shared_ptr
Недостатки:
- Два heap allocation (один для объекта, один для control block)
- Может быть exception-unsafe в некоторых случаях
auto ptr = std::shared_ptr<MyClass>(new MyClass(42, "Hello"));
Способ 3: Копирование существующего shared_ptr
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>(42, "test");
std::shared_ptr<MyClass> ptr2 = ptr1; // refcount = 2
Способ 4: Перемещение shared_ptr
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
std::shared_ptr<MyClass> ptr2 = std::move(ptr1);
// ptr1 -> nullptr, refcount не меняется
Способ 5: Преобразование из производного класса
class Derived : public Base { };
std::shared_ptr<Derived> derived = std::make_shared<Derived>();
std::shared_ptr<Base> base = derived; // Автоматическое преобразование
Способ 6: Динамический каст
std::shared_ptr<Base> base = std::make_shared<Derived>();
std::shared_ptr<Derived> derived =
std::dynamic_pointer_cast<Derived>(base);
Другие касты:
std::static_pointer_cast<T>(ptr); // static cast
std::const_pointer_cast<T>(ptr); // const cast
std::reinterpret_pointer_cast<T>(ptr); // reinterpret cast (C++17)
Способ 7: С кастомным deletером
auto deleter = [](MyClass* ptr) {
// Кастомная логика очистки
delete ptr;
};
auto ptr = std::shared_ptr<MyClass>(
new MyClass(),
deleter
);
Сравнение способов
| Метод | Безопасность | Производительность | Рекомендация |
|---|---|---|---|
| make_shared | Отличная | Быстро | ДА |
| new + конструктор | Хорошая | Медленно | Только если нужен deleter |
| Копирование | Безопасно | Копия | Редко |
| Перемещение | Безопасно | Быстро | Часто |
Пример: Фабрика
class ObjectFactory {
public:
static std::shared_ptr<MyClass> create(int x, const std::string& s) {
return std::make_shared<MyClass>(x, s);
}
};
int main() {
auto obj = ObjectFactory::create(42, "test");
std::vector<std::shared_ptr<MyClass>> collection;
collection.push_back(obj); // refcount увеличится
return 0;
}
Лучшие практики
✅ ДА:
- Используй std::make_shared по умолчанию
- Перемещай shared_ptr, не копируй
- Используй weak_ptr для избежания циклических ссылок
❌ НЕТ:
- Не смешивай shared_ptr и raw pointers
- Не создавай разные shared_ptr на один объект
- Не используй this в конструкторе для создания shared_ptr
std::make_shared — это gold standard для создания управляемых объектов в современном C++.