Lors de la création de variables locales, est-il correct d'utiliser (const) auto&
ou auto
?
par exemple:
SomeClass object;
const auto result = object.SomeMethod();
ou const auto& result = object.SomeMethod();
Où SomeMethod () renvoie une valeur non primitive - peut-être un autre type défini par l'utilisateur. Ma compréhension est que const auto& result
c'est correct puisque le résultat retourné par SomeMethod () appellerait le constructeur de copie pour le type retourné. S'il vous plait corrigez moi si je me trompe.
Qu'en est-il des types primitifs? Je suppose que const auto sum = 1 + 2;
c'est correct.
Cela s'applique-t-il également aux boucles basées sur la plage?
for(const auto& object : objects)
auto
fonctionne (sauf pour le cas particulier deinitializer_list
s, qui sont non déduit dans un contexte de modèle), puisauto
tapez déduction.Réponses:
auto
etauto &&
couvrent la plupart des cas:À utiliser
auto
lorsque vous avez besoin d'une copie locale. Cela ne produira jamais de référence. Le constructeur de copie (ou de déplacement) doit exister, mais il peut ne pas être appelé, en raison de l' optimisation d' élision de copie .À utiliser
auto &&
lorsque vous ne vous souciez pas de savoir si l'objet est local ou non. Techniquement, cela produira toujours une référence, mais si l'initialiseur est temporaire (par exemple, la fonction retourne par valeur), il se comportera essentiellement comme votre propre objet local.De plus,
auto &&
ne garantit pas non plus que l'objet sera modifiable. Étant donné unconst
objet ou une référence, il en déduiraconst
. Cependant, la modifiabilité est souvent supposée, compte tenu du contexte spécifique.auto &
etauto const &
sont un peu plus précis:auto &
garantit que vous partagez la variable avec autre chose. C'est toujours une référence et jamais un temporaire.auto const &
est commeauto &&
, mais fournit un accès en lecture seule.Il n'y a pas de différence.
Oui. Appliquer les principes ci-dessus,
auto &&
pour la possibilité de modifier et d'annuler les valeurs de la séquence dans la boucle. (Autrement dit, à moins que le conteneur ne fournisse une vue en lecture seule, par exemplestd::initializer_list
, auquel cas ce sera effectivement unauto const &
.)auto &
pour modifier les valeurs de la séquence de manière significative.auto const &
pour un accès en lecture seule.auto
pour travailler avec des copies (modifiables).Vous mentionnez également
auto const
sans référence. Cela fonctionne, mais ce n'est pas très couramment utilisé car il y a rarement un avantage à accéder en lecture seule à quelque chose que vous possédez déjà.la source
auto&
semble être un bon choix. Mais à utiliserconst auto&
lorsque vous souhaitez ajouter une constness qui n'est pas déjà là.auto&&
est pour le transfert, ce qui, je pense, arrive plus souvent que Sutter ne le pense. Par exemple, vous voudrez peut-être stocker une valeur de retour parauto&&
, puis la «transférer» vers deux choses, comme std :: cout pour voir la valeur pour le débogage et la transmettre également à une autre fonction. J'utilisais plus souvent l'auto &&, mais j'ai été mordu une ou deux fois par des choses inattendues. J'aurais aimé faire plus attention à ce qui n'a pas fonctionné!auto&&
est lié à une fonctionnalité de langage manquante, qui devrait permettre de diviser toute instruction en instructions plus petites. La partie manquante est l'extension de la durée de vie ... J'ai mis pas mal d'efforts pour résoudre ce problème mais personne ne l'a remarqué. Ne mettez pas trop de stock dans le punditry :)Oui, il est correct d'utiliser
auto
etauto&
pour les variables locales. Lors de l'obtention du type de retour d'une fonction, il est également correct de l'utiliserauto&
. Cela s'applique également aux boucles basées sur la plage.Les règles générales d'utilisation
auto
sont:auto x
quand vous souhaitez travailler avec des copies.auto &x
quand vous voulez travailler avec des éléments originaux et pouvez les modifier.auto const &x
quand vous souhaitez travailler avec des éléments originaux et ne les modifierez pas.Vous pouvez en savoir plus sur le spécificateur automatique ici .
la source
auto
utilise le même mécanisme de déduction de type que les modèles, la seule exception que je sache étant celle des listes brace-init, qui sont déduites parauto
asstd::initializer_list
, mais non déduites dans un contexte de modèle.auto x = expression;
fonctionne en supprimant d'abord tous les qualificatifs de référence et cv du type de l'expression de droite, puis en faisant correspondre le type. Par exemple, si vous avez
const int& f(){...}
alorsauto x = f();
déduitx
commeint
, et nonconst int&
.L'autre forme,
auto& x = expression
ne supprime pas les qualificatifs cv, donc, en utilisant l'exemple ci-dessus,
auto& x = f()
déduitx
commeconst int&
. Les autres combinaisons ajoutent simplement des qualificatifs cv.Si vous voulez que votre type soit toujours déduit avec des qualificatifs cv-ref, utilisez le tristement célèbre
decltype(auto)
en C ++ 14, qui utilise lesdecltype
règles de déduction de type.Donc, en un mot, si vous voulez des copies, utilisez
auto
, si vous voulez des références, utilisezauto&
. À utiliserconst
chaque fois que vous voulez uneconst
-ness supplémentaire .EDIT Il existe un cas d'utilisation supplémentaire,
auto&& x = expression;
qui utilise les règles de réduction des références, comme dans le cas de la transmission des références dans le code du modèle. Si
expression
est une lvalue, alorsx
est une référence lvalue avec les qualificatifs cv deexpression
. Siexpression
est une rvalue, alorsx
est une référence rvalue.la source
rvalues
. Existe-t-il un moyen simple de tester? Et comment pouvez-vous avoir une rvalue qualifiée cv? Lors du retour de la fonction, le cv est ignoré.auto && x = std::move< const int >( 5 );
déclareraint const && x
, bien qu'elles soient rarement utilisées.Oui. L'auto n'est rien d'autre qu'un type déduit du compilateur, utilisez donc des références là où vous utiliseriez normalement des références et des copies locales (automatiques) là où vous utiliseriez normalement des copies locales. L'utilisation ou non d'une référence est indépendante de la déduction de type.
Légal? Oui, avec le const. Meilleur entrainement? Probablement pas, non. Du moins, pas avec C ++ 11. Surtout pas, si la valeur renvoyée par SomeMethod () est déjà temporaire. Vous voudrez en savoir plus sur la sémantique de déplacement C ++ 11, l'élision de copie et l'optimisation de la valeur de retour: https://juanchopanzacpp.wordpress.com/2014/05/11/want-speed-dont-always-pass-by- valeur/
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199
https://isocpp.org/wiki/faq/ctors#return-by-value-optimization
Oui, c'est bien.
Oui, c'est bien aussi. J'écris ce genre de code au travail tout le temps.
la source