Introduction : pourquoi les files d'attente de tâches en C++ ?
\nImaginez que vous faites la queue à la caisse d'un supermarché. Le premier arrivé est servi en premier. En programmation, cette structure s'appelle une file d'attente (queue). C'est l'un des types de données fondamentaux qui fonctionne selon le principe FIFO (First In, First Out) — « premier arrivé, premier sorti ».
\nEn C++, les files d'attente de tâches sont utilisées partout : du traitement des requêtes réseau à la gestion des threads dans les applications multithread. Pour un programmeur débutant, comprendre les files d'attente est une étape vers la maîtrise de sujets plus complexes, comme la programmation asynchrone et les patrons de conception.
\nDans cet article, nous allons voir comment créer et utiliser les files d'attente en C++, examiner le conteneur standard std::queue, écrire plusieurs exemples pratiques et discuter des erreurs typiques des débutants.
Bases de la file d'attente : théorie et premier exemple
\nQu'est-ce qu'une file d'attente ?
\nUne file d'attente est un type de données abstrait qui prend en charge deux opérations principales :
\n- \n
- Ajout d'un élément à la fin de la file d'attente (enqueue / push); \n
- Extraction d'un élément du début de la file d'attente (dequeue / pop). \n
En C++, la file d'attente standard est implémentée dans le fichier d'en-tête <queue> en tant que classe std::queue. Par défaut, elle utilise std::deque comme conteneur sous-jacent, mais vous pouvez le remplacer par std::list.
Premier exemple : file d'attente de nombres
\nÉcrivons un programme simple qui crée une file d'attente d'entiers, y ajoute plusieurs valeurs et les affiche à l'écran.
\n#include <iostream>\n#include <queue>\n\nint main() {\n std::queue<int> my_queue;\n\n // Ajout d'éléments à la file d'attente\n my_queue.push(10);\n my_queue.push(20);\n my_queue.push(30);\n\n std::cout << "Premier élément (front) : " << my_queue.front() << std::endl;\n std::cout << "Dernier élément (back) : " << my_queue.back() << std::endl;\n std::cout << "Taille de la file d'attente : " << my_queue.size() << std::endl;\n\n // Extraction des éléments\n while (!my_queue.empty()) {\n std::cout << "Extrait : " << my_queue.front() << std::endl;\n my_queue.pop();\n }\n\n return 0;\n}\nRésultat du programme :
\nPremier élément (front) : 10\nDernier élément (back) : 30\nTaille de la file d'attente : 3\nExtrait : 10\nExtrait : 20\nExtrait : 30\nNotez que front() renvoie le premier élément (qui sera extrait ensuite), et back() renvoie le dernier élément ajouté. La méthode pop() supprime l'élément mais ne le renvoie pas — c'est important à retenir !
Méthodes principales de std::queue
\nPour travailler efficacement avec une file d'attente, vous devez connaître toutes ses méthodes. Voici la liste complète :
\n- \n
push(const T& value)— ajoute un élément à la fin de la file d'attente ; \n pop()— supprime le premier élément (ne le renvoie pas) ; \n front()— renvoie une référence au premier élément ; \n back()— renvoie une référence au dernier élément ; \n empty()— vérifie si la file d'attente est vide (renvoie true/false) ; \n size()— renvoie le nombre d'éléments. \n
Important : Avant d'appeler front() ou pop(), vérifiez toujours si la file d'attente n'est pas vide avec empty(). Tenter d'accéder aux éléments d'une file d'attente vide entraîne un comportement indéfini (probablement un plantage du programme).
Exemple pratique : file d'attente de tâches
\nMaintenant, simulons une situation réelle. Supposons que nous ayons un système qui traite des commandes. Chaque commande est une structure avec un numéro et une description. Nous plaçons les commandes dans une file d'attente