Sobes.tech
Middle

Co víte o chytrých ukazatelích v C++?

sobes.tech AI

Odpověď od AI

Chytré ukazatele - jsou RAII-obaly nad běžnými (surovými) ukazateli v C++, které poskytují automatickou správu životnosti alokované paměti a zabraňují únikům.

Hlavní typy chytrých ukazatelů v knihovně C++:

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

std::unique_ptr

  • Vlastní zdroj exkluzivně.
  • Není možné jej kopírovat, ale lze jej přesunout.
  • Používá se pro jedinečné vlastnictví zdroje.
  • Náklady jsou minimální, ekvivalentní surovému ukazateli.
// příklad 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 kompilace: unique_ptr nelze kopírovat
    std::unique_ptr<int> ptr3 = std::move(ptr); // Přesun vlastnictví
    std::cout << *ptr3 << std::endl; // 10
    // std::cout << *ptr << std::endl; // Nedefinované chování: ptr je nyní prázdný
    return 0;
}

std::shared_ptr

  • Umožňuje více ukazatelům sdílet jeden zdroj.
  • Používá počítadlo odkazů. Paměť je uvolněna, když je počet odkazů nulový.
  • Může být kopírován. Každá kopie zvyšuje počítadlo odkazů.
  • Má vyšší režii než unique_ptr kvůli správě počítadla odkazů.
// shared_ptr příklad
#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írování, zvyšuje use_count
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 2)
    std::shared_ptr<int> ptr3 = ptr1; // Další kopie
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 3)
    return 0;
}

std::weak_ptr

  • Nevlastní zdroj a nezvyšuje počítadlo odkazů.
  • Používá se k řešení problému cyklických odkazů mezi shared_ptr.
  • Umožňuje přístup ke zdroji, na který ukazuje shared_ptr, ale nebrání jeho odstranění.
  • Pro přístup ke zdroji je třeba weak_ptr převést na shared_ptr pomocí metody lock().
// weak_ptr příklad
#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 byl již odstraněn." << std::endl;
    }

    shared_ptr_int.reset(); // Zdroj je uvolněn

    if (auto locked_ptr = weak_ptr_int.lock()) {
        std::cout << *locked_ptr << std::endl;
    } else {
        std::cout << "Zdroj byl již odstraněn." << std::endl; // Zdroj byl již odstraněn
    }
    return 0;
}

Použití chytrých ukazatelů je dobrou praxí v moderním C++, protože výrazně snižuje pravděpodobnost chyb při správě paměti.