Quels sont les avantages / inconvénients de l'utilisation du auto
mot - clé, en particulier dans les boucles for?
for(std::vector<T>::iterator it = x.begin(); it != x.end(); it++ )
{
it->something();
}
for(std::map<T>::iterator it = x.begin(); it != x.end(); it++ )
{
it->second->something();
}
for(auto it = x.begin(); it != x.end(); it++ )
{
it->??
}
On dirait que si vous ne savez pas si vous avez un itérateur pour une carte ou un vecteur vous ne savez pas si vous souhaitez utiliser first
ou second
ou seulement des propriétés d'accès directement de l'objet, non?
Cela me rappelle le débat C # sur l'opportunité d'utiliser le mot clé var
. L'impression que j'ai jusqu'à présent est que dans le monde C ++, les gens sont prêts à adopter le auto
mot - clé avec moins de combat que var
dans le monde C #. Pour moi, mon premier instinct est que j'aime connaître le type de la variable afin que je puisse savoir quelles opérations je peux m'attendre à y effectuer.
var
? J'ai manqué ça.for (auto& it : x)
(ou sans référence si vous voulez copier)x
et que vous ne savez même pas ce quex
c'est, vous ne devriez pas écrire cette boucle en premier lieu ;-)Réponses:
Les motivations en C ++ sont plus extrêmes, car les types peuvent devenir beaucoup plus compliqués et complexes que les types C # en raison de la métaprogrammation et d'autres choses.
auto
est plus rapide à écrire et à lire et plus flexible / maintenable qu'un type explicite. Je veux dire, voulez-vous commencer à taperCe n'est même pas le type complet. J'ai raté quelques arguments de modèle.
la source
auto
. Intentionnellement.typedef
aide, maisauto
aide plus.Dans votre exemple:
il doit y avoir une déclaration pour
x
visible. Par conséquent, le type deit
doit être évident. Si le type dex
n'est pas évident, la méthode est trop longue ou la classe est trop grande.la source
x
est un très mauvais nom de variable pour un conteneur. Dans certaines situations, vous pouvez très probablement simplement regarder le nom (sémantiquement valable) et déduire les opérations possibles.x
comme exemple générique, j'ai tendance à utiliser des noms de variables assez descriptifs.Objection ! Question chargée.
Pouvez-vous m'expliquer pourquoi le troisième code contient
??
, mais pas le premier et le deuxième? Par souci d'équité, votre code doit se lire comme suit:Là. Même problème même si vous ne l'avez pas utilisé
auto
.Et dans tous les cas, la réponse est la même: le contexte compte . Vous ne pouvez pas parler de manière significative d'un morceau de code de manière isolée. Même si vous n'aviez pas utilisé de modèles mais un type concret, cela n'aurait fait que déplacer le problème ailleurs, car le lecteur de votre code devrait connaître la déclaration dudit type.
Si l'utilisation de
auto
dans ces situations rend votre code illisible, vous devez considérer cela comme un signe d'avertissement qu'il y a un problème avec la conception de votre code. Bien sûr, il y a des cas où des détails de bas niveau sont importants (comme pour les opérations sur les bits ou les API héritées), auquel cas un type explicite peut faciliter la lisibilité. Mais en général - non.En ce qui concerne
var
(puisque vous l'avez mentionné explicitement), il existe également un vaste consensus dans la communauté C # pour l' utilisationvar
. Les arguments contre son utilisation reposent généralement sur des erreurs .la source
T
est opaque à l'utilisateur commeauto
. Pourtant, l'un est censé être bien et l'autre non?! Cela n'a aucun sens. Dans le cas de OP,T
est un remplaçant pour un type arbitraire. En vrai code, cela peut être l'utilisation de modèles(for typename std::vector<T>::iterator…)
ou d'une interface de classe. Dans les deux cas, le type réel est caché à l'utilisateur, et pourtant nous écrivons régulièrement ce code sans problème.auto
. Il est trivial de voir quelles opérationsx
prennent en charge à partir du contexte. En fait, le type ne vous donne aucune information supplémentaire: dans les deux cas, vous avez besoin d'un secondaire (IDE, documentation, connaissances / mémoire) pour vous indiquer l'ensemble des opérations prises en charge.begin
rendements , mais vous ne savezstd::vector<>::iterator
c'est. Et vous devez utiliser un mauvais outil de programmation qui ne peut pas vous donner ces informations de manière triviale. C'est très compliqué. En réalité, vous savez soit à la foisbegin
etiterator
ou non plus , et vous devez utiliser un IDE ou un éditeur qui peut rendre facilement les informations pertinentes à votre disposition . Tout éditeur IDE et de programmation moderne peut le faire.PRO
Votre code :
ne va pas compiler, en raison du nom dépendant du modèle.
Voici la syntaxe correcte:
Regardez maintenant la longueur de la déclaration de type. Cela explique pourquoi le
auto
mot clé a été introduit. Cette :est plus concis. Donc, c'est un pro.
CON
Vous devez être un peu prudent. Avec le mot-clé
auto
, vous obtenez le type que vous avez déclaré.Par exemple :
contre
Pour conclure: oui, vous devriez le faire, mais pas en abuser. Certaines personnes ont tendance à trop l'utiliser et à mettre l'auto partout, comme dans l'exemple suivant:
contre
la source
auto i = 0
. Coupable. Je fais ça. Mais c'est parce que je sais que0
c'est un type littéralint
. (et une constante octale ;-))Oui tu devrais!
auto
n'efface pas le type; même si vous "ne savez pas" ce quix.begin()
est, le compilateur sait et signalera une erreur si vous essayez d'utiliser le type incorrectement. De plus, il n'est pas inhabituel d'émulermap
avec unvector<pair<Key,Value>>
, donc le code utilisantauto
fonctionnera pour les deux représentations de dictionnaire.la source
Oui, vous devez utiliser
auto
comme règle par défaut. Il présente des avantages bruts par rapport à la spécification explicite du type:C'est là que vous avez le choix. Il y a aussi des cas où vous n'avez pas le choix:
Pourvu que vous sachiez exactement ce
auto
que cela fait, cela n'a aucun inconvénient.la source