L'inférence de type avec le mot-clé auto
L'inférence de type fait référence à la déduction automatique du type de données d'une expression dans un langage de programmation.
Avant C++11, chaque type de données devait être explicitement déclaré au moment de la compilation. Après C++11, de nouveaux mots-clés permettent à un programmeur de laisser la déduction de type au compilateur lui-même.
Avec les capacités d'inférence de type, nous pouvons passer moins de temps à écrire des choses que le compilateur connaît déjà.
Important : Comme tous les types sont déduits uniquement dans la phase de compilation, le temps de compilation augmente légèrement mais cela n'affecte pas le temps d'exécution du programme.
Vous utilisez le mot clé auto pour indiquer que le compilateur doit déduire le type d'une variable.
Exemple 1 : Utilisation simple de auto
auto m {10}; // m est de type int
auto n {200UL}; // n est de type unsigned long
auto p {std::numbers::pi}; // p est de type doubleExplication :
- Le compilateur déduit les types de m, n et p à partir des valeurs initiales fournies.
10est un entier →mestint.200ULest un unsigned long →nestunsigned long.std::numbers::piest un double →pestdouble.
Exemple 2 : Autres formes d'initialisation
Vous pouvez également utiliser la notation fonctionnelle ou d'affectation avec auto :
auto m = 10; // m est de type int
auto n = 200UL; // n est de type unsigned long
auto p = std::numbers::pi; // p est de type doubleCe n'est pas vraiment ainsi que le mot-clé auto est censé être utilisé. Lorsque vous définissez des variables de types fondamentaux, vous pourriez souvent aussi bien spécifier le type explicitement.
Nous reviendrons sur auto plus tard, où il est appliqué de manière plus appropriée et beaucoup plus utile (avec des itérateurs, des expressions complexes, etc.).
Attention : auto et les initialisateurs entre accolades
Vous devez être très prudent lorsque vous utilisez des initialisateurs entre accolades avec le mot-clé auto. Le comportement a changé selon les versions de C++.
Exemple 3 : Évolution du comportement
auto i {10}; // i est std::initializer_list<int> !!!
auto pi = {3.14159}; // pi est std::initializer_list<double>
auto liste1{1, 2, 3}; // liste1 est std::initializer_list<int>
auto liste2 = {4, 5, 6}; // liste2 est std::initializer_list<int>Dans ces versions, auto i {10}; ne donne pas un int mais une liste d'initialisation !
auto i {10}; // i est de type int ✓
auto pi = {3.14159}; // pi est std::initializer_list<double>
auto liste1{1, 2, 3}; // ERREUR : ne compile pas !
auto liste2 = {4, 5, 6}; // liste2 est std::initializer_list<int>Correction : auto i {10}; donne bien un int maintenant.
auto liste1{1,2,3}; est interdit (plusieurs valeurs).
Exemple concret des différences
/* C++11 et C++14 */
auto i {10}; // i est de type std::initializer_list<int>
auto j = 10; // j est de type int (notation avec =)
// i et j n'ont pas le même type !
/* C++17 et versions ultérieures */
auto i {10}; // i est de type int (enfin!)
auto j = 10; // j est de type int (identique)
// i et j ont maintenant le même typeauto variable {valeur};→ type = type devaleur(si valeur unique).auto variable = {valeur};→ type =std::initializer_list<T>.auto variable {v1, v2, v3};→ erreur de compilation.auto variable = {v1, v2, v3};→ type =std::initializer_list<T>.
Recommandations pratiques
Si votre compilateur prend correctement en charge C++17 :
- Vous pouvez utiliser l'initialisation entre accolades pour initialiser n'importe quelle variable avec une valeur unique, à condition de ne pas la combiner avec une affectation (
=). auto x {5};→ OK, x est un int.auto x = {5};→ attention, x est une liste d'initialisation.
Si votre compilateur n'est pas encore complètement à jour (pré-C++17) :
- Ne jamais utiliser d'initialiseurs entre accolades avec auto.
- Préférer indiquer explicitement le type ou utiliser l'affectation ou la notation fonctionnelle.
auto x = 5;plutôt queauto x {5};
Tableau récapitulatif
| Syntaxe | C++11/14 | C++17+ |
|---|---|---|
auto x {10}; | std::initializer_list<int> | int |
auto x = {10}; | std::initializer_list<int> | std::initializer_list<int> |
auto x {1, 2, 3}; | std::initializer_list<int> | Erreur de compilation |
auto x = {1, 2, 3}; | std::initializer_list<int> | std::initializer_list<int> |
Deviner les types déduits
Pour chacune des déclarations suivantes, quel type le compilateur déduira-t-il pour la variable (en supposant un compilateur C++17 conforme) ?
auto a = 42;auto b {42};auto c = {42};auto d = 3.14f;auto e {3.14};auto f = {1, 2, 3, 4};auto g {1, 2, 3, 4};auto h = "bonjour";
auto a = 42;→int(affectation simple)auto b {42};→int(C++17, accolade avec valeur unique)auto c = {42};→std::initializer_list<int>(affectation + accolades)auto d = 3.14f;→float(suffixe f)auto e {3.14};→double(C++17, valeur unique)auto f = {1, 2, 3, 4};→std::initializer_list<int>auto g {1, 2, 3, 4};→ Erreur de compilation (plusieurs valeurs sans =)auto h = "bonjour";→const char*(pointeur vers chaîne constante)
- auto demande au compilateur de déduire automatiquement le type d'une variable.
- L'inférence de type a lieu à la compilation, pas à l'exécution.
- Le comportement de
autoavec les accolades a changé entre C++11/14 et C++17. - En C++17 :
auto x {valeur};déduit le type devaleur(si unique). - En C++17 :
auto x = {v1, v2};déduitstd::initializer_list<T>. - En C++17 :
auto x {v1, v2};est interdit (erreur). - Pour les types simples, spécifier explicitement le type est souvent aussi simple que d'utiliser
auto. - L'utilité réelle de
autoapparaît avec les types complexes (itérateurs, expressions lambda, etc.).
Discussion (0)
Soyez le premier à laisser un commentaire !
Laisser un commentaire
Votre commentaire sera visible après modération.