Comment réussir un entretien C++ : les meilleures questions avec des exemples de code
L'entretien C++ est l'une des épreuves les plus difficiles pour un développeur. Ce langage combine la puissance de la programmation bas niveau avec les paradigmes modernes de la POO et des templates. Pour réussir l'entretien, il ne suffit pas de connaître la syntaxe, il faut aussi comprendre comment fonctionnent la mémoire, le compilateur et la bibliothèque standard. Dans cet article, nous analyserons le top 10 des questions les plus fréquemment posées lors des entretiens C++, avec des réponses détaillées et des exemples de code.
1. Qu'est-ce que le RAII et pourquoi est-il nécessaire ?
RAII (Resource Acquisition Is Initialization) est l'un des idiomes clés du C++. Le principe est simple : une ressource (mémoire, fichier, mutex) est acquise dans le constructeur d'un objet et libérée dans le destructeur. Cela garantit un nettoyage correct même en cas d'exceptions.
Exemple de code incorrect (sans RAII) :
void process() { int* ptr = new int(42); // ... code qui peut lever une exception delete ptr; // fuite si l'exception survient avant delete}Exemple avec RAII (utilisation de std::unique_ptr) :
#include <memory>
void process() { std::unique_ptr<int> ptr = std::make_unique<int>(42); // ... code avec exceptions // ptr est automatiquement supprimé en sortant de la portée}Pourquoi cette question est posée : RAII est le fondement de la gestion sécurisée des ressources en C++. Sans lui, il est impossible d'écrire du code fiable.
2. Quelle est la différence entre une fonction virtuelle et une fonction virtuelle pure ?
Une fonction virtuelle (virtual) peut être redéfinie dans une classe dérivée, mais possède une implémentation dans la classe de base. Une fonction virtuelle pure (= 0) n'a pas d'implémentation dans la classe de base et rend la classe abstraite — il est impossible de créer un objet de cette classe.
Exemple :
class Base {public: virtual void foo() { std::cout << "Base foo"; } // virtuelle virtual void bar() = 0; // virtuelle pure};
class Derived : public Base {public: void foo() override { std::cout << "Derived foo"; } void bar() override { std::cout << "Derived bar"; }};Question complémentaire : Comment fonctionne la vtable ? Le compilateur crée une table de fonctions virtuelles pour chaque classe possédant des méthodes virtuelles. Chaque objet contient un pointeur vers cette table (vptr). Lors de l'appel d'une fonction virtuelle, une répartition dynamique est effectuée via la vtable.
3. Quels sont les pointeurs intelligents en C++ et quand les utiliser ?
En C++11, trois types de pointeurs intelligents sont apparus :
- std::unique_ptr — propriété exclusive. Impossible à copier, uniquement déplaçable. Idéal pour les ressources avec un seul propriétaire.
- std::shared_ptr — propriété partagée. Utilise un compteur de références. Adapté lorsque plusieurs objets doivent posséder une même ressource.
- std::weak_ptr — ne possède pas la ressource, mais peut observer un shared_ptr. Nécessaire pour briser les références cycliques.
Exemple d'utilisation de unique_ptr :
#include <memory>
class MyClass { /* ... */ };
void example() { auto ptr = std::make_unique<MyClass>(); // auto ptr2 = ptr; // Erreur ! Impossible de copier auto ptr3 = std::move(ptr); // OK, déplacement}Exemple de shared_ptr et weak_ptr pour éviter les références cycliques :
struct Node { std::shared_ptr<Node> next; std::weak_ptr<Node> prev; // weak_ptr pour éviter le cycle};4. Qu'est-ce que la sémantique de déplacement et std::move ?
La sémantique de déplacement permet de « déplacer » les ressources d'un objet vers un autre au lieu de les copier. C'est particulièrement utile pour les objets temporaires ou lorsque la copie est coûteuse (par exemple, std::string ou