web-dev-qa-db-fra.com

C ++ auto mot-clé. Pourquoi est-ce magique?

De tout le matériel que j'ai utilisé pour apprendre le C++, auto a toujours été un spécificateur de durée de stockage bizarre qui ne servait à rien. Mais récemment, j’ai rencontré un code qui l’utilisait comme un nom de type. Par curiosité, j'ai essayé, et cela suppose le type de ce que je lui attribue!

Soudain, les itérateurs STL et, enfin, tout ce qui utilise des modèles est 10 fois plus facile à écrire. J'ai l'impression d'utiliser un langage "amusant" comme Python.

Où ce mot-clé a-t-il été toute ma vie? Voulez-vous lancer mes rêves en disant que c'est exclusif à Visual Studio ou non portable?

126
Anne Quinn

auto était un mot-clé que C++ "héritait" de C et qui y était depuis presque toujours, mais qu'il n'utilisait pratiquement jamais car il n'y avait que deux conditions possibles: soit ce n'était pas autorisé, soit c'était assumé par défaut.

L'utilisation de auto pour désigner un type déduit était nouvelle avec C++ 11.

À la fois, auto x = initializer déduit le type de x du type de initializer de la même manière que la déduction de type de modèle fonctionne pour les modèles de fonction. Considérons un modèle de fonction comme ceci:

template<class T>
int whatever(T t) { 
    // point A
};

Au point A, un type a été attribué à T en fonction de la valeur transmise pour le paramètre à whatever. Quand vous faites auto x = initializer;, le même type de déduction est utilisé pour déterminer le type de x à partir du type de initializer utilisé pour l’initialiser.

Cela signifie que la plupart des mécanismes de déduction de types dont un compilateur a besoin pour implémenter auto étaient déjà présents et utilisés pour les modèles sur tout compilateur qui tentait même d'implémenter C++ 98/03. En tant que tel, ajouter le support de auto était apparemment assez facile pour la plupart des équipes de compilation - il a été ajouté assez rapidement, et il semble qu'il y ait eu peu de bogues liés à cela.

Lorsque cette réponse a été écrite à l'origine (en 2011, avant que l'encre ne soit sèche sur le standard C++ 11), auto était déjà assez portable. De nos jours, il est parfaitement portable parmi tous les compilateurs traditionnels. Les seules raisons évidentes à éviter seraient si vous devez écrire du code compatible avec un compilateur C, ou si vous avez un besoin spécifique de cibler un compilateur de niche qui, à votre connaissance, ne le prend pas en charge (par exemple, quelques personnes écrivent encore du code). pour MS-DOS utilisant des compilateurs de Borland, Watcom, etc., qui n’ont pas connu de mises à niveau importantes depuis des décennies). Si vous utilisez une version raisonnablement à jour de l’un des compilateurs traditionnels, il n’ya aucune raison de l’éviter du tout.

128
Jerry Coffin

Il suffit de prendre un mot clé généralement inutile et de lui donner une nouvelle fonctionnalité améliorée. Il est standard en C++ 11, et la plupart des compilateurs C++ avec même un support C++ 11 le supporteront.

19
Nicol Bolas

Cette fonctionnalité n'a pas été là toute votre vie. Il est pris en charge dans Visual Studio depuis la version 2010. C'est une nouvelle fonctionnalité C++ 11, donc elle n'est pas exclusive à Visual Studio et est/sera portable. La plupart des compilateurs le supportent déjà.

11

Pour les variables, spécifie que le type de la variable en cours de déclaration sera automatiquement déduit de son initialiseur. Pour les fonctions, spécifie que le type de retour est un type de retour final ou sera déduit de ses instructions de retour (depuis C++ 14).

Syntaxe

auto variable initializer   (1) (since C++11)

auto function -> return type    (2) (since C++11)

auto function   (3) (since C++14)

decltype(auto) variable initializer (4) (since C++14)

decltype(auto) function (5) (since C++14)

auto :: (6) (concepts TS)

cv(optional) auto ref(optional) parameter   (7) (since C++14)

Explication

1) Lors de la déclaration de variables dans la portée d'un bloc, dans la portée d'un espace de noms, dans les instructions d'initialisation de boucles for, etc., le mot clé auto peut être utilisé comme spécificateur de type. Une fois que le type de l'initialiseur a été déterminé, le compilateur détermine le type qui remplacera le mot clé auto à l'aide des règles de déduction d'argument de modèle à partir d'un appel de fonction (voir Déduction d'argument de modèle # Autres contextes pour plus de détails). Le mot-clé auto peut être accompagné de modificateurs, tels que const ou &, qui participeront à la déduction de type. Par exemple, étant donné const auto& i = expr;, Le type de i est exactement le type de l'argument u dans un modèle imaginaire template<class U> void f(const U& u) si l'appel de fonction f(expr) a été compilé. Par conséquent, auto && peut être déduit en tant que référence lvalue ou référence rvalue selon l'initialiseur, qui est utilisé dans la boucle for basée sur l'intervalle. Si auto est utilisé pour déclarer plusieurs variables, les types déduits doivent correspondre. Par exemple, la déclaration auto i = 0, d = 0.0; Est mal formée, alors que la déclaration auto i = 0, *p = &i; Est bien formée et l'auto est déduite comme étant int.

2) Dans une déclaration de fonction qui utilise la syntaxe de type retour final, le mot-clé auto n'effectue pas de détection de type automatique. Cela ne fait que partie de la syntaxe.

3) Dans une déclaration de fonction qui n'utilise pas la syntaxe de type de retour final, le mot-clé auto indique que le type de retour sera déduit de l'opérande de son instruction de retour à l'aide des règles de déduction d'argument de modèle.

4) Si le type déclaré de la variable est decltype (auto), le mot-clé auto est remplacé par l'expression (ou la liste d'expressions) de son initialiseur et le type réel est déduit à l'aide des règles de decltype.

5) Si le type de retour de la fonction est déclaré avec decltype (auto), le mot-clé auto est remplacé par l'opérande de son instruction de retour et le type de retour réel est déduit à l'aide des règles de decltype.

6) Un spécificateur de nom imbriqué de la forme auto :: est un espace réservé qui est remplacé par un type de classe ou d'énumération suivant les règles applicables à la déduction d'espace réservé de type contraint.

7) Une déclaration de paramètre dans une expression lambda. (depuis C++ 14) Une déclaration de paramètre de fonction. (concepts TS)

Notes Jusqu'en C++ 11, auto avait la sémantique d'un spécificateur de durée de stockage. Le mélange de variables et de fonctions automatiques dans une seule déclaration, comme dans auto f() -> int, i = 0; n'est pas autorisé.

Pour plus d'informations: http://en.cppreference.com/w/cpp/language/auto

8
Prathamesh Aware

Cela ne va nulle part ... c'est une nouvelle fonctionnalité standard C++ dans l'implémentation de C++ 11. Ceci étant dit, s'il s'agit d'un outil formidable pour simplifier les déclarations d'objet et nettoyer la syntaxe de certains paradigmes d'appel (c'est-à-dire, des boucles for basées sur une plage), il ne faut pas en abuser/en abuser :-)

3
Jason