Sobes.tech
Middle

Jak działa unique_ptr w C++?

sobes.tech AI

Odpowiedź od AI

std::unique_ptr — to inteligentny wskaźnik, który implementuje wyłączną własność obiektu dynamicznie przydzielonego. Zapewnia automatyczne zarządzanie pamięcią: obiekt, na który wskazuje unique_ptr, jest automatycznie usuwany podczas niszczenia unique_ptr.

Kluczowe cechy:

  • Wyłączna własność: W dowolnym momencie tylko jeden unique_ptr może posiadać dany obiekt.
  • Brak kopiowania: unique_ptr nie może być kopiowany. Zapobiega to wielokrotnemu własnościowi tego samego obiektu i problemowi "podwójnego usunięcia".
  • Semantyka przenoszenia: Własność obiektu może być przekazana z jednego unique_ptr do innego za pomocą semantyki przenoszenia (std::move).
  • Konfigurowalny deleter: Można dostarczyć własny deleter do zarządzania specyficznymi metodami zwalniania zasobów.

Zasada działania opiera się na RAII (Resource Acquisition Is Initialization): zasób (pamięć dynamiczna) jest nabywany podczas tworzenia obiektu (unique_ptr) i zwalniany podczas jego niszczenia.

#include <memory> // Dla unique_ptr
#include <iostream>

class MyClass {
public:
    MyClass() { std::cout << "MyClass utworzony\n"; }
    ~MyClass() { std::cout << "MyClass zniszczony\n"; }
};

int main() {
    {   
        // Tworzenie unique_ptr posiadającego obiekt MyClass
        std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>(); 
        
        // W tym momencie, ptr1 jest wyłącznym właścicielem obiektu
        // auto ptr2 = ptr1; // Błąd kompilacji: kopiowanie zabronione

        // Przeniesienie własności z ptr1 do ptr2
        std::unique_ptr<MyClass> ptr2 = std::move(ptr1); 
        
        // Po przeniesieniu, ptr1 nie posiada już obiektu (jest nullptr)
        if (!ptr1) {
            std::cout << "ptr1 nie posiada obiektu: " << (ptr1 ? "Tak" : "Nie") << "\n";
        }

        // Zakres dla ptr2 kończy się tutaj.
        // ptr2 jest niszczony, a obiekt MyClass, którym zarządza, jest automatycznie usuwany.
    } // Obiekt MyClass jest usuwany tutaj

    std::cout << "Koniec main.\n";

    return 0;
}

Porównanie z raw pointer:

Cecha raw pointer std::unique_ptr
Własność zasobu Nieokreślona Wyłączna
Automatyczne usuwanie Nie Tak
Semantyka kopiowania Tak Nie (tylko przenoszenie)
Ryzyko wycieków pamięci Wysokie Niskie

Ogólnie rzecz biorąc, unique_ptr jest preferowaną metodą zarządzania pamięcią dynamiczną w C++11 i nowszych wersjach, gdy wymagana jest ścisła własność i automatyczne zwalnianie zasobów.