Programmation • IoT

Chapitre 9 – Quelques outils du C++ moderne

Document réservé

Vous consultez actuellement la présentation publique de ce chapitre.

Les documents PDF complets, comprenant les développements théoriques, les exemples détaillés et les exercices, sont disponibles sur demande.

Pour obtenir un accès, contactez-moi via la page Contact en indiquant les domaines qui vous intéressent (C++, ESP-IDF, électronique, etc.).

9 Quelques outils du C++ moderne 9.2 auto : laisser le compilateur déduire un type . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3 Quand auto devient réellement utile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.5 nullptr : représenter un pointeur nul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.6 Pourquoi nullptr est préférable à 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.7 La boucle for basée sur un intervalle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.8 Valeur, référence et référence constante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.9 enum class : des énumérations plus sûres . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.10 Pourquoi enum class est plus sûr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.11 constexpr : calculer à la compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.14 Décomposer une structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.15 Structured bindings et conteneurs associatifs . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.16 Représenter l’absence d’une valeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.21 Des outils différents pour rendre l’intention explicite . . . . . . . . . . . . . . . . . . . . . . . 2026 – C++ Partie III Quelques outils du C++ moderne
Accueil
Quelques outils du C++ moderne Le C++ moderne ne se résume pas à quelques grandes nouveautés comme les pointeurs intelligents, la sémantique de déplacement, les conteneurs ou les expressions lambda, et depuis C++11, puis avec les versions suivantes du langage, de nombreux outils plus modestes ont également été introduits. Pris séparément, certains peuvent sembler n’être plus des commodités syntaxiques que des nouveautés fondamentales. Ensemble, ils permettent cependant d’écrire un code : • plus expressif ; • plus facile à maintenir. Plusieurs de ces outils ont déjà été rencontrés dans les chapitres précédents et nous allons maintenant préciser leur rôle. auto : laisser le compilateur déduire un type Le mot-clé auto demande au compilateur de déduire le type d’une variable à partir de son initialisation, Le compilateur déduit respectivement On pourrait donc écrire : L’intérêt de auto n’est donc pas particulièrement évident dans ces exemples ! 2026 – C++ Partie III Quelques outils du C++ moderne Quand auto devient réellement utile Considérons un itérateur std::vector<double>::iterator it = valeurs.begin(); Nous pouvons écrire plus simplement : auto it = valeurs.begin(); Le type reste parfaitement déterminé à la compilation et il n’y a aucun typage dynamique car le compilateur connaît exactement le type de it. Ensuite, nous avons également rencontré auto avec les expressions lambda : auto carre = [](double x) Le type exact de l’objet lambda est généré par le compilateur, auto est donc ici particulièrement naturel. • auto ne signifie pas que la variable n’a pas de type, le type existe toujours et il est déterminé à la compilation, C++ reste un langage fortement typé. auto signifie simplement : Déduis le type à partir de l’expression d’initialisation. Ne pas abuser de auto L’utilisation de auto doit améliorer la lisibilité et non la diminuer. auto temperature = 21.5; est parfaitement compréhensible mais lorsqu’il devient difficile de déterminer ce que représente une expression, écrire explicitement le type peut rendre le programme plus clair. Il ne faut donc pas considérer auto comme une règle obligatoire, c’est un outil. nullptr : représenter un pointeur nul Dans du code ancien, on rencontre fréquemment Le C++ moderne introduit
Accueil
2026 – C++ Partie III Quelques outils du C++ moderne Nous écrivons donc : Le mot-clé nullptr représente explicitement une valeur de pointeur nul. Pourquoi nullptr est préférable à 0 Considérons deux fonctions surchargées, void afficher(int x) std::cout << « entier\n »; void afficher(int* p) std::cout << « pointeur\n »; appelle la version recevant un entier, en revanche : désigne clairement une valeur de pointeur nul et permet de sélectionner la surcharge correspondant au • Dans du code C++ moderne, on utilise : pour représenter un pointeur nul. • On évite d’utiliser 0 ou NULL dans ce rôle, NULL est utilisé en C. La boucle for basée sur un intervalle Nous avons déjà rencontré la boucle : for (double x : valeurs) std::cout << x << ’\n’; Il s’agit d’une boucle for basée sur un intervalle (range-based for loop) qui permet de parcourir directement les éléments d’un conteneur.
Accueil
2026 – C++ Partie III Quelques outils du C++ moderne Valeur, référence et référence constante Il faut cependant rester attentif à la manière dont la variable de boucle est déclarée, avec : for (double x : valeurs) chaque élément est copié dans x, avec for (double& x : valeurs) x est une référence vers l’élément du conteneur et donc nous pouvons donc modifier les éléments : for (double& x : valeurs) Si nous voulons seulement consulter les éléments sans les copier : for (const double& x : valeurs) std::cout << x << ’\n’; Cette dernière forme devient particulièrement intéressante pour les objets dont la copie pourrait être coûteuse. enum class : des énumérations plus sûres Le C++ possède depuis longtemps les énumérations classiques : Elles présentent cependant certaines limitations et le C++ moderne propose les énumérations fortement Nous utilisons alors Couleur c = Couleur::rouge; indique explicitement que rouge appartient à l’énumération Couleur.
Accueil
2026 – C++ Partie III Quelques outils du C++ moderne Pourquoi enum class est plus sûr appartiennent à deux types différents et le compilateur empêche donc de les mélanger accidentellement, de plus, une valeur d’un enum class n’est pas implicitement convertie en entier. Si une conversion est réellement souhaitée, elle doit être exprimée explicitement, par exemple : int n = static_cast<int>(Etat::marche); Nous retrouvons ici les conversions explicites déjà étudiées précédemment. constexpr : calculer à la compilation permet d’indiquer qu’une valeur ou un calcul peut être évalué lors de la compilation lorsque les conditions nécessaires sont réunies, par exemple : constexpr double pi = 3.141592653589793; La valeur est connue à la compilation. Une fonction constexpr Une fonction peut également être déclarée constexpr : constexpr int carre(int x) Nous pouvons alors écrire : constexpr int n = carre(5); Ici, le calcul peut être effectué pendant la compilation, mais une fonction constexpr peut également être appelée avec une valeur connue seulement pendant l’exécution :
Accueil
2026 – C++ Partie III Quelques outils du C++ moderne Dans ce cas, le calcul est naturellement effectué pendant l’exécution. • constexpr ne signifie pas simplement : Cette fonction est toujours exécutée à la compilation. • Une fonction constexpr peut également être utilisée pendant l’exécution, le contexte dans lequel elle est appelée détermine si une évaluation à la compilation est requise ou possible. Les structured bindings Depuis C++17, il est possible de décomposer certains objets en plusieurs variables. std::pair<int, double> mesure{12, 3.7}; Traditionnellement, nous pourrions écrire : int numero = mesure.first; double valeur = mesure.second; Avec une structured binding : auto [numero, valeur] = mesure; Les deux éléments sont directement associés à deux noms. Décomposer une structure Nous obtenons directement deux variables :
Accueil
2026 – C++ Partie III Quelques outils du C++ moderne contenant respectivement les deux composantes de p. Comme avec les autres constructions du langage, il faut être attentif à la différence entre copie et référence. permet de travailler directement sur les membres de p. Structured bindings et conteneurs associatifs Les structured bindings deviennent particulièrement agréables avec des conteneurs comme std::map, par std::map<std::string, double> temperatures; temperatures[« Geneve »] = 21.5; temperatures[« Lausanne »] = 20.8; Nous pouvons parcourir la map ainsi for (const auto& [ville, temperature] : temperatures) Cette écriture évite de manipuler explicitement les membres first et second des paires contenues dans la Représenter l’absence d’une valeur Une fonction ne peut pas toujours produire un résultat valable. Supposons une fonction recherchant une valeur dans un ensemble de données, nous pourrions être tentés de retourner : Aucune valeur n’a été trouvée. Mais que se passe-t-il si -1 est lui-même un résultat parfaitement valable ? Nous mélangeons alors deux informations différentes : • la valeur du résultat ; • l’existence ou l’absence d’un résultat. Le C++17 propose pour cela :
Accueil
2026 – C++ Partie III Quelques outils du C++ moderne Pour utiliser std::optional, nous incluons Une fonction peut alors retourner : std::optional<double> Cette fonction peut fournir un double, mais elle peut également ne fournir aucune valeur. std::optional<double> chercher( const std::vector<double>& valeurs, for (double x : valeurs) return std::nullopt; représente explicitement l’absence de valeur. Nous pouvons écrire : auto resultat = chercher(valeurs, 10.0); std::cout << *resultat << ’\n’; std::cout << « Aucun resultat\n »; teste si l’objet contient une valeur et si une valeur existe :
Accueil
2026 – C++ Partie III Quelques outils du C++ moderne permet d’y accéder. Nous retrouvons volontairement une syntaxe rappelant celle des pointeurs. value() et value_or() Un optional possède également la fonction membre : std::cout << resultat.value() << ’\n’; Si aucune valeur n’est présente, value() déclenche une exception de type : std::bad_optional_access Nous reviendrons précisément sur le mécanisme des exceptions dans la partie consacrée aux exceptions. Une autre fonction membre permet de fournir une valeur de remplacement : double x = resultat.value_or(0.0); Si resultat contient une valeur, celle-ci est utilisée, sinon, 0.0 est utilisé. optional ou exception ? L’absence d’une valeur n’est pas nécessairement une erreur, par exemple, rechercher un élément dans un ensemble peut parfaitement échouer dans le fonctionnement normal d’un programme. Dans ce cas, un type comme : exprime naturellement : Il peut y avoir un résultat ou ne pas y en avoir. Une exception correspond à une autre idée : elle permet de signaler qu’une situation exceptionnelle empêche le déroulement normal d’une opération, cette distinction sera étudiée plus précisément dans le chapitre consacré aux exceptions. Des outils différents pour rendre l’intention explicite Les outils étudiés dans ce chapitre répondent à des problèmes différents. auto permet au compilateur de déduire un type lorsque son écriture explicite n’apporte rien ou devient nullptr exprime sans ambiguïté l’absence d’un objet désigné par un pointeur. La boucle for basée sur un intervalle exprime directement l’idée de parcourir les éléments d’un ensemble. enum class permet de représenter des ensembles de valeurs symboliques avec un typage plus strict.
Accueil
2026 – C++ Partie III Quelques outils du C++ moderne constexpr permet d’exprimer qu’un calcul peut participer à une évaluation à la compilation. Les structured bindings permettent de donner directement des noms aux différentes composantes d’un objet décomposable. permet d’exprimer dans le système de types qu’une valeur peut être présente ou absente. Le point commun de ces outils n’est donc pas simplement leur date d’apparition dans le langage mais ils permettent au programmeur d’exprimer plus précisément son intention. Le C++ moderne fournit de nombreux outils qui complètent les mécanismes fondamentaux du langage. permet la déduction du type à partir d’une initialisation. représente explicitement un pointeur nul. for (const auto& x : conteneur) permet un parcours compact et sûr des éléments d’un conteneur. Les énumérations : offrent un typage plus strict que les anciennes énumérations. permet de rendre certains calculs utilisables lors de la compilation. Les structured bindings : auto [a, b] = objet; permettent de décomposer certains objets.
Accueil
2026 – C++ Partie III Quelques outils du C++ moderne représente explicitement une valeur qui peut être présente ou absente. Ces outils illustrent une évolution importante du C++ moderne, celle d’exprimer davantage d’informations directement dans le langage et dans les types, plutôt que de reposer sur des conventions implicites.
Accueil
P4-Chap-09 Quelques outils du C++ moderne
Accueil
Termes à ajouter au glossaire
Contenu

Inscription

×
Cancel