J'ai utilisé le nouveau auto
mot clé disponible dans la norme C ++ 11 pour les types de modèles compliqués, ce pour quoi je pense qu'il a été conçu. Mais je l'utilise aussi pour des choses comme:
auto foo = std::make_shared<Foo>();
Et plus sceptiquement pour:
auto foo = bla(); // where bla() return a shared_ptr<Foo>
Je n'ai pas vu beaucoup de discussions sur ce sujet. Il semble que cela auto
pourrait être surutilisé, car un type est souvent une forme de documentation et de vérification de l'intégrité. Où tracez-vous la ligne d'utilisation auto
et quels sont les cas d'utilisation recommandés pour cette nouvelle fonctionnalité?
Pour clarifier: je ne demande pas d'avis philosophique; Je demande l'utilisation prévue de ce mot-clé par le comité standard, éventuellement avec des commentaires sur la façon dont cette utilisation prévue est réalisée dans la pratique.
Note latérale: Cette question a été déplacée vers SE.Programmers, puis de nouveau vers Stack Overflow. Une discussion à ce sujet peut être trouvée dans cette méta-question .
auto
mot - clé, alors vous savez comment il est censé être utilisé. C'est ce que je demande, en tant que nouveau utilisateur de cette fonctionnalité, comment dois-je l'utiliser?var
(c'est-à-dire, une fois que les gens ont fini par penser que ce n'était pas du typage dynamique après tout). Si vous le souhaitez, vous pouvez commencer par cette question et passer par les questions connexes.auto foo = bla();
«mauvais» est clairement une opinion, pas un fait, ce qui rend cette question et répond à une discussion, ce qui la rend pertinente pour Programmers SE, ce qui est exactement ce que les votes serrés indiquent. / haussement d'épaulesRéponses:
Je pense que l'on devrait utiliser le
auto
mot - clé chaque fois qu'il est difficile de dire comment écrire le type à première vue, mais le type du côté droit d'une expression est évident. Par exemple, en utilisant:pour obtenir le type de clé composite
boost::multi_index
, même si vous savez qu'il l'estint
. Vous ne pouvez pas simplement écrireint
car cela pourrait être changé à l'avenir. J'écriraisauto
dans ce cas.Donc, si le
auto
mot clé améliore la lisibilité dans un cas particulier, utilisez-le. Vous pouvez écrireauto
quand il est évident pour le lecteur quel typeauto
représente.Voici quelques exemples:
la source
bla()
vous donnez en retourfoo
.Utilisez-le
auto
partout où vous le pouvez, en particulierconst auto
pour que les effets secondaires soient moins préoccupants. Vous n'aurez pas à vous soucier des types, sauf dans les cas évidents, mais ils seront toujours vérifiés statiquement pour vous, et vous pouvez éviter certaines répétitions. Lorsque celaauto
n'est pas possible, vous pouvez utiliserdecltype
pour exprimer des types sémantiquement sous forme de contrats basés sur des expressions. Votre code sera différent, mais ce sera un changement positif.la source
auto&&
dans des situations complexes edmundv.home.xs4all.nl/blog/2014/01/28/…const auto&
ou àconst auto
moins que je veuille explicitement muter ou bouger.auto str = std::string();
place destd::string str;
?Facile. Utilisez-le lorsque vous ne vous souciez pas du type. Par exemple
Tout ce qui m'importe ici, c'est ce qu'il
i
y a dans le conteneur.C'est un peu comme les typedefs.
Ici, je ne me soucie pas de savoir si
h
etw
sont des flotteurs ou des doubles, seulement qu'ils sont de tout type approprié pour exprimer les hauteurs et les poids .Ou pensez
Ici, tout ce qui m'importe, c'est que c'est un itérateur approprié, supportant
operator++()
, c'est un peu comme taper du canard à cet égard.De plus, le type de lambdas ne peut pas être orthographié, tout
auto f = []...
comme le bon style. L'alternative est de lancerstd::function
mais cela vient avec des frais généraux.Je ne peux pas vraiment concevoir un "abus" de
auto
. Le plus proche que je peux imaginer est de vous priver d'une conversion explicite en un type significatif - mais vous ne l'utiliseriez pasauto
pour cela, vous construiriez un objet du type souhaité.Si vous pouvez supprimer une certaine redondance dans votre code sans introduire d'effets secondaires, cela doit être bon de le faire.
Contre-exemples (empruntés aux réponses de quelqu'un d'autre):
Ici, nous nous soucions du type, nous devons donc écrire
Someclass i;
etfor(unsigned x = y;...
la source
auto
.Fonce. Utilisez-le
auto
partout où il facilite l'écriture de code.Chaque nouvelle fonctionnalité dans n'importe quelle langue va être surutilisée par au moins certains types de programmeurs. Ce n'est que par une surutilisation modérée par certains programmeurs expérimentés (et non par des noobs) que le reste des programmeurs expérimentés apprend les limites d'une bonne utilisation. Une surutilisation extrême est généralement mauvaise, mais pourrait être bonne car une telle surutilisation peut conduire à des améliorations de la fonctionnalité ou à une meilleure fonctionnalité pour la remplacer.
Mais si je travaillais sur du code avec plus de quelques lignes comme
où le type est indiqué zéro fois, je pourrais vouloir changer ces lignes pour inclure des types. Le premier exemple est excellent car le type est indiqué une fois, et
auto
nous évite d'avoir à écrire deux fois des types malpropres. Hourra pour C ++++. Mais montrer explicitement le type zéro fois, s'il n'est pas facilement visible dans une ligne proche, me rend nerveux, au moins en C ++ et ses successeurs immédiats. Pour d'autres langages conçus pour fonctionner à un niveau supérieur avec plus d'abstraction, de polymorphisme et de généricité, c'est bien.la source
Au C ++ et au-delà de 2012 dans le panel Ask Us Anything , il y a eu un échange fantastique entre Andrei Alexandrescu, Scott Meyers et Herb Sutter pour savoir quand utiliser et ne pas utiliser
auto
. Passez à la minute 25:03 pour une discussion de 4 minutes. Les trois haut-parleurs donnent d'excellents points qui doivent être gardés à l'esprit pour savoir quand ne pas les utiliserauto
.J'encourage fortement les gens à arriver à leur propre conclusion, mais mon emport était de l' utiliser
auto
partout sauf si :L'utilisation libérale des
explicit
aides réduit la préoccupation pour ces derniers, ce qui contribue à minimiser la durée pendant laquelle les premiers sont un problème.En reformulant ce que Herb a dit, "si vous ne faites pas X, Y et Z, utilisez
auto
. Apprenez ce que sont X, Y et Z et allez-y et utilisezauto
partout ailleurs."la source
Oui, il peut être abusé au détriment de la lisibilité. Je suggère de l'utiliser dans des contextes où les types exacts sont longs, ou inexprimables, ou non importants pour la lisibilité, et les variables sont de courte durée. Par exemple, le type d'itérateur est généralement long et n'est pas important, donc
auto
fonctionnerait:auto
ici ne nuit pas à la lisibilité.Un autre exemple est le type de règle d'analyseur, qui peut être long et alambiqué. Comparer:
avec
D'un autre côté, lorsque le type est connu et simple, c'est beaucoup mieux s'il indique explicitement:
plutôt que
la source
begin()
etend()
, ou que la taille de votre pas est autre chose qu'un, ou que vous modifiez le conteneur pendant que vous bouclez, l'instruction basée sur la plage for ne vous aidera pas.r_and_t<r_and_t<r_char_t<char>&, r_char_t<char>&>, r_char_t<char>&>
fait?space
s'agit et rechercher cela. Ce sont les informations les plus utiles de toute façon ... après tout, le problème n'est pas "de quel type est cette nouvelle variable" mais plutôt "qu'est-ce que celaspace & space & space
signifie?" Le type réel de l'expression n'est que du bruit.auto
peut être très dangereux en combinaison avec des modèles d'expression qui sont beaucoup utilisés par les bibliothèques d'algèbre linéaire telles que Eigen ou OpenCV.Les bugs causés par ce type d'erreurs sont une difficulté majeure à déboguer. Un remède possible consiste à convertir explicitement le résultat dans le type attendu si vous êtes déterminé à utiliser auto pour le style de déclaration de gauche à droite.
la source
A*B
expression soit copiée ou non dans uneauto
variable ou autre chose, le comportement que vous décrivez est toujours présent.auto
.diag(A * B)
n'a pas à gaspiller les cycles de calcul des éléments hors diagonale.J'utilise
auto
sans restriction et je n'ai rencontré aucun problème. Je finis même parfois par l'utiliser pour des types simples commeint
. Cela fait de c ++ un langage de niveau supérieur pour moi et permet de déclarer des variables en c ++ comme en python. Après avoir écrit du code python, j'écris même parfois par exempleau lieu de
C'est un cas où je dirais que c'est un abus du
auto
mot - clé.Souvent, cela ne me dérange pas quel est le type exact de l'objet, je suis plus intéressé par sa fonctionnalité, et comme les noms de fonction disent généralement quelque chose sur les objets qu'ils retournent,
auto
cela ne fait pas de mal: par exempleauto s = mycollection.size()
, je peux deviner que ces
sera une sorte d'entier, et dans les rares cas où je me soucie du type exact, vérifions ensuite le prototype de la fonction (je veux dire, je préfère avoir à vérifier quand j'ai besoin des informations, plutôt qu'à priori lorsque le code est écrit, juste au cas où cela serait utile un jour, comme dansint_type s = mycollection.size()
).Concernant cet exemple de la réponse acceptée:
Dans mon code, j'utilise toujours
auto
dans ce cas, et si je veuxx
être non signé, alors j'utilise une fonction utilitaire, nommée saymake_unsigned
, qui exprime clairement mes préoccupations:mentions légales: je viens de décrire mon utilisation, je ne suis pas compétent pour donner des conseils!
la source
auto i = MyClass()
.as_unsigned
est recommandée là-bas, ou mêmeauto w = widget{};
.L'un des problèmes majeurs du programme C ++ est qu'il vous permet d'utiliser la variable non initialisée . Cela nous amène à un comportement de programme non déterministe désagréable. Il convient de noter que le compilateur moderne lance désormais des messages d'avertissement / message appropriés si le programme se lasse de l'utiliser.
Juste pour illustrer cela, considérez le programme c ++ ci-dessous:
Si je compile ce programme en utilisant un compilateur moderne (GCC), il donne l'avertissement. Un tel avertissement peut ne pas être très évident si nous travaillons avec le vrai code de production complexe.
================================================== =============================== Maintenant, si nous changeons notre programme qui utilise auto , puis compilons nous obtenons ce qui suit:
Avec auto, il n'est pas possible d'utiliser la variable non initialisée. C'est un avantage majeur que nous pouvons obtenir (gratuitement) si nous commençons à utiliser auto .
Ce concept et d'autres grands grands concepts C ++ modernes sont expliqués par Herb Shutter, expert C ++, dans son discours sur CppCon14 :
Retour à l'essentiel! Essentiels du style C ++ moderne
la source
auto
.auto
- mais vous n'en avez pas besoin pour éviter ce problème.Un danger que j'ai noté concerne les références. par exemple
Le problème est que another_ref n'est pas réellement une référence dans ce cas, c'est MyBigObject au lieu de MyBigObject &. Vous finissez par copier un gros objet sans vous en rendre compte.
Si vous obtenez une référence directement à partir d'une méthode, vous pourriez ne pas penser à ce qu'elle est réellement.
vous auriez besoin de "auto &" ou "const auto &"
la source
Utilisez
auto
là où il est logique qu'un type soit déduit. Si vous savez que quelque chose est un entier ou que vous savez que c'est une chaîne, utilisez simplement int / std :: string, etc. ou obscurcit le code.C'est mon avis de toute façon.
la source
auto
Le mot clé ne peut être utilisé que pour une variable locale, pas pour des arguments ou des membres de classe / structure. Il est donc sûr et viable de les utiliser où vous le souhaitez. Je les utilise beaucoup. Le type est déduit au moment de la compilation, le débogueur affiche le type pendant le débogage, lesizeof
signale correctement,decltype
il donnerait le type correct - il n'y a pas de mal. Je ne compte pasauto
comme surutilisé, jamais!la source
TL; DR: Voir la règle générale en bas.
La réponse acceptée suggère la règle empirique suivante:
Mais je dirais que c'est trop restrictif. Parfois, je ne me soucie pas des types, car la déclaration est suffisamment informative sans que je prenne la peine de prendre le temps de comprendre le type. Qu'est-ce que je veux dire par là? Prenons l'exemple qui est apparu dans certaines des réponses:
Qu'est-ce qui en fait un exemple d'utilisation abusive
auto
? Est-ce mon ignorance duf()
type de retour de? Eh bien, cela pourrait effectivement aider si je le savais, mais - ce n'est pas ma principale préoccupation. Ce qui est beaucoup plus problématique, c'est celax
etf()
n'a pas beaucoup de sens. Si nous avions:au lieu de cela, alors je ne me soucie généralement pas de savoir si le type de retour de la fonction est évident ou non. En lisant la déclaration, je sais ce que je fais et j'en sais assez sur la sémantique de la valeur de retour pour ne pas ressentir le besoin de connaître également son type.
Donc ma réponse est: à utiliser
auto
chaque fois que le compilateur le permet, à moins que:Et aussi:
auto
par le type concret.la source
Une de mes amères expériences avec
auto
son utilisation avec des expressions lambda :En fait, ici
i
est résolu de fonctionner le pointeur deint(*)()
. C'est juste un simplecout
, mais imaginez quel type d'erreurs de compilation / d'exécution incorrectes il peut provoquer lorsqu'il est utilisé avectemplate
.Vous devez éviter
auto
avec de telles expressions et mettre unreturn
type approprié (ou contrôlédecltype()
)L'utilisation correcte pour l'exemple ci-dessus serait,
la source
()
à la fin. Les lambdas sont là pour agir comme des fonctions et c'est de là que vient la conversion du pointeur de fonction. Si vous voulez l'appeler tout de suite, pourquoi utiliser un lambda?auto i = 0;
fonctionne plutôt bien.auto x = []() { /* .... whatever goes in here ... */ }()
c'est mieux queauto x = /* .... whatever goes in here ... */;
, c'est-à-dire la même chose, sans le lambda? Je trouve cela plutôt inutile, pour la même raisonauto x = 42 + y - 42
est inutile.