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

Что такое unique_ptr?

1.3 Junior🔥 201 комментариев
#Язык C++

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

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

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

Что такое unique_ptr

unique_ptr — это умный указатель (smart pointer) из стандартной библиотеки C++ (заголовок <memory>), который автоматически управляет динамически выделенной памятью. Ключевая особенность: только один объект может владеть ресурсом в любой момент времени. Когда unique_ptr выходит из области видимости, память автоматически освобождается.

Основные характеристики

Единственное владение: Только один unique_ptr может владеть объектом. Это предотвращает двойное удаление и утечки памяти.

Автоматическая очистка: Когда unique_ptr уничтожается, он вызывает delete для управляемого объекта.

Zero overhead: Практически нулевые накладные расходы в сравнении с обычными указателями.

Передача владения: Владение можно передать другому unique_ptr через move-семантику.

Синтаксис и создание

#include <memory>
#include <iostream>

class MyClass {
public:
    MyClass(int value) : value_(value) {
        std::cout << "Конструктор " << value_ << std::endl;
    }
    ~MyClass() {
        std::cout << "Деструктор " << value_ << std::endl;
    }
private:
    int value_;
};

// Способ 1: Прямое создание
std::unique_ptr<MyClass> ptr1(new MyClass(42));

// Способ 2: make_unique (C++14, рекомендуется)
std::unique_ptr<MyClass> ptr2 = std::make_unique<MyClass>(42);

// Для массивов
std::unique_ptr<int[]> arr = std::make_unique<int[]>(100);

Операции с unique_ptr

Разыменование и доступ

std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>(42);

// Доступ через оператор *
MyClass& obj = *ptr;

// Доступ через оператор ->
ptr->someMethod();

// Получить обычный указатель (осторожно!)
MyClass* raw_ptr = ptr.get();

Передача владения (move-семантика)

std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>(42);
std::unique_ptr<MyClass> ptr2;

// Передача владения
ptr2 = std::move(ptr1);  // Теперь ptr1 = nullptr

// ptr1 больше не владеет объектом!
std::cout << (ptr1 == nullptr) << std::endl;  // true

Освобождение ресурса

std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>(42);
ptr.reset();  // Удалит объект, ptr = nullptr

ptr.reset(new MyClass(100));  // Удалит старый, создаст новый

MyClass* raw = ptr.release();  // Отдать владение, не удалять
delete raw;  // Нужно удалить вручную

Использование в функциях

Возврат из функции

std::unique_ptr<MyClass> createObject(int value) {
    return std::make_unique<MyClass>(value);  // RVO, move
}

std::unique_ptr<MyClass> ptr = createObject(42);

Передача в функцию

// Способ 1: По значению (передача владения)
void processObject(std::unique_ptr<MyClass> ptr) {
    ptr->someMethod();
    // ptr будет удалён в конце функции
}

std::unique_ptr<MyClass> my_ptr = std::make_unique<MyClass>(42);
processObject(std::move(my_ptr));  // my_ptr теперь nullptr

// Способ 2: По ссылке (временный доступ)
void processObject(MyClass& obj) {
    obj.someMethod();
    // obj не удаляется
}

std::unique_ptr<MyClass> my_ptr = std::make_unique<MyClass>(42);
processObject(*my_ptr);

Custom deleter

// Использование FILE* с unique_ptr
std::unique_ptr<FILE, decltype(&fclose)> file(
    fopen("data.txt", "r"), 
    &fclose
);

if (file) {
    // Использовать файл
}  // fclose будет вызван автоматически

unique_ptr vs shared_ptr

Свойствоunique_ptrshared_ptr
ВладениеТолько одинМножественное
OverheadНулевойСчётчик ссылок
ПередачаMoveCopy/Move
ПотокобезопасностьНетДа (счётчик)
ПроизводительностьЛучшеМедленнее

Лучшие практики

  1. Используйте make_unique: Это безопаснее и эффективнее
  2. Предпочитайте unique_ptr shared_ptr: Используйте shared_ptr только при необходимости
  3. Избегайте get(): Не сохраняйте raw указатели из get()
  4. Используйте move: Для передачи владения
  5. Не удаляйте вручную: unique_ptr сам управляет памятью

Заключение

unique_ptr — это фундаментальный инструмент для безопасного управления памятью в C++. Он предотвращает утечки памяти, двойное удаление и делает код более надёжным. В современном C++ (C++11 и выше) следует всегда использовать unique_ptr вместо обычных указателей для управления динамической памятью.

Что такое unique_ptr? | PrepBro