Sobes.tech
Middle

Šta znate o pametnim pokazivačima u C++?

sobes.tech АИ

Одговор од АИ

Pametni pokazivači - to su RAII omotači nad običnim (sirovim) pokazivačima u C++, koji pružaju automatsko upravljanje vremenom života alocirane memorije, sprečavajući curenje.

Glavne vrste pametnih pokazivača u standardnoj biblioteci C++:

  • std::unique_ptr
  • std::shared_ptr
  • std::weak_ptr

std::unique_ptr

  • Ekskluzivno poseduje resurs.
  • Ne može biti kopiran, ali može biti pomeren.
  • Koristi se za jedinstveno vlasništvo nad resursom.
  • Troškovi su minimalni, ekvivalentni sirovom pokazivaču.
// primer sa unique_ptr
#include <memory>
#include <iostream>

int main() {
    std::unique_ptr<int> ptr = std::make_unique<int>(10);
    std::cout << *ptr << std::endl; // 10
    // std::unique_ptr<int> ptr2 = ptr; // Greška pri kompilaciji: unique_ptr se ne kopira
    std::unique_ptr<int> ptr3 = std::move(ptr); // Premestanje vlasništva
    std::cout << *ptr3 << std::endl; // 10
    // std::cout << *ptr << std::endl; // Nedefinisano ponašanje: ptr je sada prazan
    return 0;
}

std::shared_ptr

  • Omogućava više pokazivača da zajednički poseduje jedan resurs.
  • Koristi brojač referenci. Memorija se oslobađa kada brojač dostigne nulu.
  • Može biti kopiran. Svaka kopija povećava brojač.
  • Ima veće troškove u poređenju sa unique_ptr zbog upravljanja brojačem.
// primer sa shared_ptr
#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> ptr1 = std::make_shared<int>(20);
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 1)
    std::shared_ptr<int> ptr2 = ptr1; // Kopiranje, povećava use_count
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 2)
    std::shared_ptr<int> ptr3 = ptr1; // Još jedna kopija
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 3)
    return 0;
}

std::weak_ptr

  • Ne poseduje resurs i ne povećava brojač.
  • Koristi se za rešavanje problema cikličnih referenci između shared_ptr.
  • Omogućava pristup resursu na koji ukazuje shared_ptr, ali ne sprečava njegovo brisanje.
  • Za pristup resursu, potrebno je konvertovati weak_ptr u shared_ptr pomoću metode lock().
// primer sa weak_ptr
#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> shared_ptr_int = std::make_shared<int>(30);
    std::weak_ptr<int> weak_ptr_int = shared_ptr_int;

    if (auto locked_ptr = weak_ptr_int.lock()) {
        std::cout << *locked_ptr << std::endl; // 30
    } else {
        std::cout << "Resurs je već oslobođen." << std::endl;
    }

    shared_ptr_int.reset(); // Resurs se oslobađa

    if (auto locked_ptr = weak_ptr_int.lock()) {
        std::cout << *locked_ptr << std::endl;
    } else {
        std::cout << "Resurs je već oslobođen." << std::endl; // Resurs je već oslobođen
    }
    return 0;
}

Korišćenje pametnih pokazivača je dobra praksa u savremenom C++, jer značajno smanjuje verovatnoću grešaka u upravljanju memorijom.