Sobes.tech
Middle

Čo viete o inteligentných ukazovateľoch v C++?

sobes.tech AI

Odpoveď od AI

Inteligentné ukazovatele - sú RAII obaly nad bežnými (surovými) ukazovateľmi v C++, ktoré poskytujú automatickú správu životnosti alokovanej pamäte, zabraňujúc únikom.

Hlavné typy inteligentných ukazovateľov v štandardnej knižnici C++:

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

std::unique_ptr

  • Vlastní zdroj exkluzívne.
  • Nemôže byť kopírovaný, ale môže byť presunutý.
  • Používa sa na jedinečné vlastníctvo zdroja.
  • Náklady sú minimálne, ekvivalentné surovému ukazovateľu.
// príklad s 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; // Chyba pri kompilácii: unique_ptr sa nekopíruje
    std::unique_ptr<int> ptr3 = std::move(ptr); // Presun vlastníctva
    std::cout << *ptr3 << std::endl; // 10
    // std::cout << *ptr << std::endl; // Nedefinované správanie: ptr je teraz prázdny
    return 0;
}

std::shared_ptr

  • Umožňuje viacerým ukazovateľom vlastniť jeden zdroj.
  • Používa počítadlo odkazov. Pamäť sa uvoľní, keď počet odkazov dosiahne nulu.
  • Môže byť kopírovaný. Každá kópia zvyšuje počítadlo.
  • Má vyššie náklady v porovnaní s unique_ptr kvôli správe počítadla.
// príklad s 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; // Kopírovanie, zvyšuje use_count
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 2)
    std::shared_ptr<int> ptr3 = ptr1; // Ešte jedna kópia
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 3)
    return 0;
}

std::weak_ptr

  • Nevlastní zdroj a neukladá počet odkazov.
  • Používa sa na riešenie problému cyklických odkazov medzi shared_ptr.
  • Umožňuje prístup k zdroju, na ktorý ukazuje shared_ptr, ale nebráni jeho odstráneniu.
  • Na prístup ku zdroju je potrebné previesť weak_ptr na shared_ptr pomocou metódy lock().
// príklad s 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 << "Zdroj už bol odstránený." << std::endl;
    }

    shared_ptr_int.reset(); // Zdroj sa uvoľní

    if (auto locked_ptr = weak_ptr_int.lock()) {
        std::cout << *locked_ptr << std::endl;
    } else {
        std::cout << "Zdroj už bol odstránený." << std::endl; // Zdroj bol už odstránený
    }
    return 0;
}

Používanie inteligentných ukazovateľov je dobrou praxou v súčasnom C++, pretože výrazne znižuje pravdepodobnosť chýb pri správe pamäti.