web-dev-qa-db-fra.com

C++ auto & vs auto

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 . Je comprends que const auto& result est correct car le résultat renvoyé par SomeMethod () appelle le constructeur de copie pour le type renvoyé. 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; est correct.

Cela s'applique-t-il également à la plage basée sur les boucles?

for(const auto& object : objects)
38
rohunb

auto et auto && couvrent la plupart des cas:

  • Utilisez auto lorsque vous avez besoin d’une copie locale. Cela ne produira jamais de référence. Le constructeur copy (ou move) doit exister, mais il est possible qu'il ne soit pas appelé en raison de copy elision optimization.

  • Utilisez 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 revient 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é un objet ou une référence const, il en déduira const. Cependant, la modifiabilité est souvent supposée, étant donné le contexte spécifique.

auto & et auto const & sont un peu plus spécifiques:

  • auto & garantit que vous partagez la variable avec autre chose. C'est toujours une référence et jamais à un temporaire.

  • auto const & est semblable à auto &&, mais fournit un accès en lecture seule.

Qu'en est-il des types primitifs/non primitifs?

Il n'y a pas de différence.

Cela s'applique-t-il également à la plage basée sur les boucles?

Oui. En appliquant les principes ci-dessus,

  • Utilisez auto && pour pouvoir modifier et ignorer les valeurs de la séquence dans la boucle. (Autrement dit, à moins que le conteneur ne fournisse une vue en lecture seule, telle que std::initializer_list, auquel cas ce sera effectivement un auto const &.)
  • Utilisez auto & pour modifier les valeurs de la séquence de manière significative.
  • Utilisez auto const & pour un accès en lecture seule.
  • Utilisez auto pour travailler avec des copies (modifiables).

Vous mentionnez également auto const sans référence. Cela fonctionne, mais il n’est pas très utilisé car il ya rarement un avantage à accéder en lecture seule à quelque chose que vous possédez déjà.

50
Potatoswatter

Oui, il est correct d'utiliser auto et auto& pour les variables locales . Lors de l'obtention du type de retour d'une fonction, il est également correct d'utiliser auto&. Ceci s’applique également aux plages basées sur les boucles.

Les règles générales d'utilisation de auto sont les suivantes:

  • Choisissez auto x lorsque vous souhaitez utiliser des copies. 
  • Choisissez auto &x lorsque vous souhaitez utiliser les éléments d'origine et que vous pouvez les modifier. 
  • Choisissez auto const &x lorsque vous souhaitez utiliser les éléments d'origine et ne les modifiera pas.

Vous pouvez en savoir plus sur le spécificateur automatique ici .

26
phantom

auto utilise le même mécanisme de déduction de type que les modèles, la seule exception dont je suis au courant est celle des listes brace-init, déduites par auto sous la forme std::initializer_list, mais non déduites dans un contexte de modèle.

auto x = expression;

fonctionne en supprimant d’abord tous les qualificateurs 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(){...}, alors auto x = f(); déduit x en tant que int et pas const int&.

L'autre forme, 

auto& x = expression

ne supprime pas les qualificatifs cv. Par conséquent, à l'aide de l'exemple ci-dessus, auto& x = f() déduit x en tant que const int&. Les autres combinaisons ne font qu'ajouter des qualificatifs cv.

Si vous voulez que votre type soit toujours déduit avec les qualificateurs cv-ref, utilisez l'infâme decltype(auto) en C++ 14, qui utilise les règles de déduction de type decltype.

Donc, en un mot, si vous voulez des copies, utilisez auto, si vous voulez des références, utilisez auto&. Utilisez const chaque fois que vous souhaitez ajouter const- ness.


EDIT Il y a un cas d'utilisation supplémentaire,

auto&& x = expression;

qui utilise les règles de réduction de référence, comme dans le cas du renvoi de références dans un code de modèle. Si expression est une lvalue, alors x est une référence de lvalue avec les qualificatifs cv de expression. Si expression est une valeur rvalue, alors x est une référence rvalue. 

6
vsoftco

Lors de la création de variables locales, est-il correct d'utiliser (const) auto & ou auto?

Oui. L'auto n'est rien d'autre qu'un type déduit par le compilateur, utilisez donc des références où vous utiliseriez normalement des références, et des copies locales (automatiques) 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.

Où SomeMethod () renvoie une valeur non primitive, par exemple un autre type défini par l'utilisateur. Si j'ai bien compris, const auto & result est correct car le résultat renvoyé par SomeMethod () appelle le constructeur de copie pour le type renvoyé. S'il vous plait corrigez moi si je me trompe.

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 des mouvements C++ 11, l’élision de copie et l’optimisation de la valeur renvoyée: https://juanchopanzacpp.wordpress.com/2014/05/11/want-speed-dont-always -pass-by-value/

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=199

https://isocpp.org/wiki/faq/ctors#return-by-value-optimization

Qu'en est-il des types primitifs? Je suppose que const auto sum = 1 + 2; est correct.

Oui c'est bon.

Cela s'applique-t-il également à la plage basée sur les boucles?

pour (const auto & objet: objets)

Oui, c'est aussi bien. J'écris ce genre de code au travail tout le temps.

1
tweej