Sobes.tech
Middle

Wat weet je over smart pointers in C++?

sobes.tech AI

Antwoord van AI

Slimme pointers zijn RAII-wrappers over gewone (ruwe) pointers in C++, die automatische geheugenbeheer bieden en geheugenlekken voorkomen.

De belangrijkste typen slimme pointers in de standaardbibliotheek van C++:

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

std::unique_ptr

  • Bezit de resource exclusief.
  • Kan niet worden gekopieerd, maar wel worden verplaatst.
  • Wordt gebruikt voor het exclusieve eigendom van de resource.
  • De overhead is minimaal, gelijk aan die van een ruwe pointer.
// voorbeeld van 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; // Fout bij compilatie: unique_ptr kan niet worden gekopieerd
    std::unique_ptr<int> ptr3 = std::move(ptr); // Verplaats eigendom
    std::cout << *ptr3 << std::endl; // 10
    // std::cout << *ptr << std::endl; // Onbepaald gedrag: ptr is nu leeg
    return 0;
}

std::shared_ptr

  • Laat meerdere pointers toe om gezamenlijk een resource te bezitten.
  • Gebruikt een referentieteller. Het geheugen wordt vrijgegeven wanneer de teller op nul staat.
  • Kan worden gekopieerd. Elke kopie verhoogt de teller.
  • Heeft hogere overhead dan unique_ptr vanwege het beheer van de teller.
// voorbeeld van 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; // Kopie, verhoogt use_count
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 2)
    std::shared_ptr<int> ptr3 = ptr1; // Nog een kopie
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 3)
    return 0;
}

std::weak_ptr

  • Bezit de resource niet en verhoogt de teller niet.
  • Wordt gebruikt om het probleem van cyclische referenties tussen shared_ptr op te lossen.
  • Biedt toegang tot de resource waarnaar shared_ptr wijst, maar voorkomt niet dat deze wordt verwijderd.
  • Om toegang te krijgen tot de resource, moet weak_ptr worden geconverteerd naar shared_ptr met behulp van de lock()-methode.
// voorbeeld van 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 << "Resource is vrijgegeven." << std::endl;
    }

    shared_ptr_int.reset(); // Resource wordt vrijgegeven

    if (auto locked_ptr = weak_ptr_int.lock()) {
        std::cout << *locked_ptr << std::endl;
    } else {
        std::cout << "Resource is vrijgegeven." << std::endl; // Resource is vrijgegeven.
    }
    return 0;
}

Het gebruik van slimme pointers is een goede praktijk in moderne C++, omdat het de kans op geheugenfouten aanzienlijk vermindert.