Resource acquisition is initialization

Problème en C

void f() {
    Point* p = malloc(sizeof(Point));
    //...
    
    //⚠ là C détruit le pointeur p, mais pas la zone mémoire qui contient le Point
}
void f() {
    Point p = {.x = 5, .y = 3};
    //...
    
    // là C détruit p
}

RAII c'est utiliser le mécanisme de destruction pour détruire les ressources. Du coup, l'idée est d'utiliser la programmation objet pour gérer les ressources (mémoire, fichier, etc.).

## Programmation objet en C++

Elle est similaire à Python. Les différences sont :

  • on a des champs et méthodes privées / protégées / publics
  • on a surtout, en plus du constructeur, un destructeur.

Définition d'une classe

class RadixTree {
    RadixTree() {
        //constructeur
    }

    ~RadixTree() {
        //destructeur
    }
}

Durée de vie

void f() {
    Point p = {.x = 5, .y = 3};
    //...
    
    // là C détruit p
}

C++ appelle le destructeur au moment où la mémoire est désalloué (là quand on dépile le contexte sur la pile d'appel, comme en C). Du coup, avec constructeur et destructeur, on peut gérer les ressources, sachant que le compilateur va faire que le destructeur est appelé dès que l'objet est détruit :

  • au constructeur, on alloue la mémoire, on ouvre un fichier
  • au destructeur, on libère la mémoire, on ferme un fichier

En plus C++ a un système d'exception, compatible avec la durée de vie des objets ! Donc si une exception est levé, la mémoire est bien libérée et le destructeur est appelé.

Avantages

  • A l'utilisation des ressources, le code est léger. Pas besoin d'écrire explicitement freeRadixTree(...)
  • Impossible d'oublier de libérer la mémoire, même en cas d'exception car c'est fait dans le destructeur
  • C'est bien organisé. On sait où trouver la création et la libération de ressources : respectivement dans le constructeur et le destructeur.

### Terminologie

Utiliser les constructeurs et destructeurs pour gérer les ressources s'appelle "Resource acquisition is initialization" (RAII). D'autres personnes appellent ça "scope bound resource management".

RAII est utilisé en C++11 et Rust.