Sobes.tech
Middle

Ce știi despre pointerii inteligenți în C++?

sobes.tech AI

Răspuns de la AI

Pointerii inteligenți sunt ambalaje RAII peste pointerii obișnuiți (crudi) în C++, care oferă o gestionare automată a duratei de viață a memoriei alocate, prevenind scurgerile.

Tipurile principale de pointeri inteligenți în biblioteca standard C++:

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

std::unique_ptr

  • Deține resursa în mod exclusiv.
  • Nu poate fi copiat, dar poate fi mutat.
  • Este utilizat pentru deținerea unică a resursei.
  • Costurile suplimentare sunt minime, echivalente cu un pointer crud.
// exemplu de 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; // Eroare de compilare: unique_ptr nu poate fi copiat
    std::unique_ptr<int> ptr3 = std::move(ptr); // Mutarea deținerii
    std::cout << *ptr3 << std::endl; // 10
    // std::cout << *ptr << std::endl; // Comportament nedefinit: ptr este acum gol
    return 0;
}

std::shared_ptr

  • Permite mai multor pointeri să dețină în comun o resursă.
  • Utilizează un contor de referințe. Memoria este eliberată când contorul ajunge la zero.
  • Poate fi copiat. Fiecare copie crește contorul de referințe.
  • Are costuri mai mari comparativ cu unique_ptr din cauza gestionării contorului.
// exemplu de 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; // Copie, crește use_count
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 2)
    std::shared_ptr<int> ptr3 = ptr1; // Altă copie
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 3)
    return 0;
}

std::weak_ptr

  • Nu deține resursa și nu crește contorul de referințe.
  • Este utilizat pentru a rezolva problema referințelor ciclice între shared_ptr.
  • Permite accesul la resursa indicată de shared_ptr, dar nu împiedică ștergerea acesteia.
  • Pentru a accesa resursa, trebuie convertit weak_ptr în shared_ptr folosind metoda lock().
// exemplu de 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 << "Resursa a fost eliberată." << std::endl;
    }

    shared_ptr_int.reset(); // Resursa este eliberată

    if (auto locked_ptr = weak_ptr_int.lock()) {
        std::cout << *locked_ptr << std::endl;
    } else {
        std::cout << "Resursa a fost eliberată." << std::endl; // Resursa a fost eliberată.
    }
    return 0;
}

Utilizarea pointerilor inteligenți este o practică bună în C++ modern, deoarece reduce semnificativ probabilitatea erorilor de gestionare a memoriei.