Назад к вопросам
Senior
108
questionbank
Как реализовать умный указатель для одного и нескольких объектов?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Для одного объекта: unique_ptr или shared_ptr.
Для нескольких объектов: shared_ptr (владение) или weak_ptr (наблюдение без участия в управлении временем жизни).
#include <memory>
#include <vector>
// Пример класса объекта
class MyObject {
public:
MyObject() { /* Конструктор */ }
~MyObject() { /* Деструктор */ }
};
// Для одного объекта: unique_ptr (единственное владение)
void single_unique_ptr() {
std::unique_ptr<MyObject> ptr = std::make_unique<MyObject>();
// Объект будет автоматически удален при выходе из области видимости
}
// Для одного объекта: shared_ptr (совместное владение)
void single_shared_ptr() {
std::shared_ptr<MyObject> ptr = std::make_shared<MyObject>();
// Количество владельцев увеличивается
std::shared_ptr<MyObject> another_ptr = ptr;
// Объект будет удален, когда последний shared_ptr перестанет на него ссылаться
}
// Для нескольких объектов: vector с shared_ptr
void multiple_shared_ptr() {
std::vector<std::shared_ptr<MyObject>> objects;
objects.push_back(std::make_shared<MyObject>());
objects.push_back(std::make_shared<MyObject>());
// Каждый объект управляется своим shared_ptr в векторе
// Объекты будут удалены после удаления соответствующих shared_ptr
}
// Для нескольких объектов: vector с unique_ptr
void multiple_unique_ptr() {
std::vector<std::unique_ptr<MyObject>> objects;
objects.push_back(std::make_unique<MyObject>());
objects.push_back(std::make_unique<MyObject>());
// В данном случае vector владеет уникальными указателями
// Объекты будут удалены при выходе из области видимости вектора
// Примечание: unique_ptr нельзя копировать, только перемещать (move)
std::unique_ptr<MyObject> moved_ptr = std::move(objects[0]);
}
Сравнение unique_ptr и shared_ptr:
| Особенность | std::unique_ptr |
std::shared_ptr |
|---|---|---|
| Владение | Единственное | Совместное (счетчик ссылок) |
| Копирование | Нет (только перемещение) | Да |
| Производительность | Немного выше (нет накладных расходов на счетчик ссылок) | Немного ниже (счетчик ссылок) |
| Циклические ссылки | Не защищает | Может привести к утечкам памяти (требуется weak_ptr) |
std::weak_ptr используется для наблюдения за объектом, управляемым shared_ptr, без увеличения счетчика ссылок, предотвращая проблемы циклических ссылок.
#include <memory>
class Node {
public:
std::shared_ptr<Node> next;
std::weak_ptr<Node> previous; // Использование weak_ptr для избежания циклической ссылки
Node() = default;
~Node() { /* Деструктор */ }
};
void weak_ptr_example() {
std::shared_ptr<Node> node1 = std::make_shared<Node>();
std::shared_ptr<Node> node2 = std::make_shared<Node>();
node1->next = node2;
node2->previous = node1; // Используем weak_ptr
// Можно получить shared_ptr из weak_ptr для доступа к объекту
if (std::shared_ptr<Node> locked_node = node2->previous.lock()) {
// Если объект еще жив
// ... работаем с locked_node
} else {
// Объект уже удален
}
}