Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое 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_ptr | shared_ptr |
|---|---|---|
| Владение | Только один | Множественное |
| Overhead | Нулевой | Счётчик ссылок |
| Передача | Move | Copy/Move |
| Потокобезопасность | Нет | Да (счётчик) |
| Производительность | Лучше | Медленнее |
Лучшие практики
- Используйте make_unique: Это безопаснее и эффективнее
- Предпочитайте unique_ptr shared_ptr: Используйте shared_ptr только при необходимости
- Избегайте get(): Не сохраняйте raw указатели из get()
- Используйте move: Для передачи владения
- Не удаляйте вручную: unique_ptr сам управляет памятью
Заключение
unique_ptr — это фундаментальный инструмент для безопасного управления памятью в C++. Он предотвращает утечки памяти, двойное удаление и делает код более надёжным. В современном C++ (C++11 и выше) следует всегда использовать unique_ptr вместо обычных указателей для управления динамической памятью.