Sobes.tech
Middle

Que savez-vous des pointeurs intelligents en C++?

sobes.tech IA

Réponse de l'IA

Les pointeurs intelligents sont des wrappers RAII autour des pointeurs classiques (bruts) en C++, offrant une gestion automatique de la durée de vie de la mémoire allouée, évitant ainsi les fuites.

Les principaux types de pointeurs intelligents dans la bibliothèque standard de C++ :

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

std::unique_ptr

  • Possède la ressource de manière exclusive.
  • Ne peut pas être copié, mais peut être déplacé.
  • Utilisé pour la possession unique de la ressource.
  • Les coûts supplémentaires sont minimes, équivalents à un pointeur brut.
// exemple 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; // Erreur de compilation : unique_ptr ne se copie pas
    std::unique_ptr<int> ptr3 = std::move(ptr); // Déplacement de possession
    std::cout << *ptr3 << std::endl; // 10
    // std::cout << *ptr << std::endl; // Comportement indéfini : ptr est maintenant vide
    return 0;
}

std::shared_ptr

  • Permet à plusieurs pointeurs de partager la possession d'une ressource.
  • Utilise un compteur de références. La mémoire est libérée lorsque le compteur atteint zéro.
  • Peut être copié. Chaque copie augmente le compteur de références.
  • A des coûts supplémentaires plus élevés comparé à unique_ptr en raison de la gestion du compteur.
// exemple 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, augmente use_count
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 2)
    std::shared_ptr<int> ptr3 = ptr1; // Une autre copie
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 3)
    return 0;
}

std::weak_ptr

  • Ne possède pas la ressource et n'augmente pas le compteur de références.
  • Utilisé pour résoudre le problème de références cycliques entre shared_ptr.
  • Permet d'accéder à la ressource pointée par shared_ptr, mais ne l'empêche pas d'être supprimée.
  • Pour accéder à la ressource, il faut convertir weak_ptr en shared_ptr en utilisant la méthode lock().
// exemple 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 << "La ressource a été libérée." << std::endl;
    }

    shared_ptr_int.reset(); // La ressource est libérée

    if (auto locked_ptr = weak_ptr_int.lock()) {
        std::cout << *locked_ptr << std::endl;
    } else {
        std::cout << "La ressource a été libérée." << std::endl; // La ressource a été libérée.
    }
    return 0;
}

L'utilisation de pointeurs intelligents est une bonne pratique en C++ moderne, car elle réduit considérablement la probabilité d'erreurs dans la gestion de la mémoire.