Sobes.tech
Middle

Как работи unique_ptr в C++?

sobes.tech AI

Отговор от AI

std::unique_ptr — това е интелигентен указател, който реализира изключително владение върху динамично заделен обект. Той осигурява автоматично управление на паметта: обектът, към който сочи unique_ptr, се премахва автоматично при унищожаването на unique_ptr.

Ключови характеристики:

  • Изключително владение: Във всеки момент само един unique_ptr може да притежава конкретен обект.
  • Липса на копиране: unique_ptr не може да бъде копиран. Това предотвратява множествено владение върху един и същ обект и проблема "двойно изтриване".
  • Семантика на преместване: Владеенето на обекта може да бъде прехвърлено от един unique_ptr на друг чрез семантиката на преместване (std::move).
  • Настройваем изтривател: Може да се предостави собствен изтривател (deleter) за управление на специфични начини за освобождаване на ресурсите.

Принципът на работа е базиран на RAII (Resource Acquisition Is Initialization): ресурсът (динамично заделената памет) се придобива при създаването на обекта (unique_ptr) и се освобождава при унищожаването му.

#include <memory> // За unique_ptr
#include <iostream>

class MyClass {
public:
    MyClass() { std::cout << "MyClass създаден\n"; }
    ~MyClass() { std::cout << "MyClass унищожен\n"; }
};

int main() {
    {   
        // Създаване на unique_ptr, който притежава обект MyClass
        std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>(); 
        
        // В този момент ptr1 е изключителен собственик на обекта
        // auto ptr2 = ptr1; // Грешка при компилация: копирането е забранено

        // Прехвърляне на владение от ptr1 към ptr2
        std::unique_ptr<MyClass> ptr2 = std::move(ptr1); 
        
        // След преместването ptr1 вече не притежава обекта (става nullptr)
        if (!ptr1) {
            std::cout << "ptr1 притежава обект: " << (ptr1 ? "Да" : "Не") << "\n";
        }

        // Областта на видимост за ptr2 приключва.
        // ptr2 се унищожава, и обектът MyClass, който притежава, се премахва автоматично.
    } // Обектът MyClass се унищожава тук

    std::cout << "Край на main.\n";

    return 0;
}

Сравнение с raw pointer:

Характеристика raw pointer std::unique_ptr
Владеене на ресурса Не е определено Изключително
Автоматично изтриване Не Да
Семантика на копиране Да Не (само преместване)
Утечки на паметата Висок риск Нисък риск

Общо взето, unique_ptr е предпочитаният начин за управление на динамична памет в C++11 и по-нови версии, когато е необходима строга собственост и автоматично освобождаване на ресурсите.