Назад к вопросам
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 {
        // Объект уже удален
    }
}