C++11, varient en fonction de boucle: obtenir l'élément par valeur ou par référence à const
La lecture de quelques exemples de gamme à base de boucles, ils suggèrent deux principales façons Un, Deux, Trois, Quatre
std::vector<MyClass> vec;
for (auto &x : vec)
{
//x is a reference to an item of vec
//We can change vec's items by changing x
}
ou
for (auto x : vec)
{
//Value of x is copied from an item of vec
//We can not change vec's items by changing x
}
Bien.
Lorsque nous n'avons pas besoin de changer vec
éléments, de l'OMI, des Exemples suggèrent d'utiliser la deuxième version (en valeur). Pourquoi ils n'ont pas de proposer quelque chose qui const
références (Au moins je n'ai pas trouvé toute suggestion directe):
for (auto const &x : vec) //<-- see const keyword
{
//x is a reference to an const item of vec
//We can not change vec's items by changing x
}
N'est-il pas mieux? N'est-il pas d'éviter une copie redondante dans chaque itération alors que c'est une const
?
Vous devez vous connecter pour publier un commentaire.
Si vous ne voulez pas modifier les éléments ainsi que voulez éviter de faire des copies, puis
auto const &
est le bon choix:Celui qui vous propose d'utiliser
auto &
est faux. Les ignorer.Voici un rappel:
auto x
quand vous voulez travailler avec des copies.auto &x
quand vous voulez travailler avec des éléments d'origine et peut les modifier.auto const &x
quand vous voulez travailler avec des éléments d'origine et de ne pas les modifier.const auto &x
est équivalent à votre troisième choix.auto const &x
, mais c'est la même syntaxe. C'est juste que ce dernier est plus claire et lisible de mise en forme.auto&&
lorsque vous ne voulez pas faire un inutile copie, et ne se soucient pas si vous le modifiez ou pas, et vous voulez juste travailler.const
pour vous. Toutefois, s'il seraitauto const &
, ouauto const
a peu de différence. Moi je préfèreauto const &
juste pour être plus cohérent.const auto &
surconst auto
est que le point de l'ensemble de l'auto est ainsi que si vous modifiez le type que vous n'avez pas à modifier la déclaration... qui signifie que si c'était un type de base et vous faire un gros complexe de classe, vous n'aurez pas à le changer pour éviter la copie qu'il était en train de faire.Si vous avez un
std::vector<int>
oustd::vector<double>
, alors il est acceptable d'utiliserauto
(avec la valeur de la copie) au lieu deconst auto&
, depuis la copie d'unint
ou undouble
est bon marché:Mais si vous avez un
std::vector<MyClass>
, oùMyClass
a certains non-trivial sémantique de copie (par exemple,std::string
, certains complexes de classe personnalisée, etc.) alors je vous suggérons d'utiliserconst auto&
pour éviter profonde des copies:Alors qu'ils donnent une mauvaise suggestion.
Car ils donnent une mauvaise suggestion 🙂 Ce que vous mentionnez est correct. Si vous ne voulez observer un objet, il n'est pas nécessaire de créer une copie, et il n'est pas nécessaire d'avoir un non-
const
référence.EDIT:
Je vois les références lien fournissent tous des exemples de l'itération sur une plage de
int
valeurs ou de quelque autre type de données fondamental. Dans ce cas, puisque la copie d'unint
n'est pas cher, la création d'une copie est essentiellement équivalent à (si pas plus efficace que l') ayant une observationconst &
.Ce n'est toutefois pas le cas en général pour les types définis par l'utilisateur. Udt peut être cher à la copie, et si vous n'avez pas une raison pour la création d'une copie (telles que la modification de l'objet récupéré, sans altérer l'original), alors il est préférable d'utiliser un
const &
.int
, et la copie de la valeur n'est pas cher. Fondamentalement, il fait le même effet qu'unconst &
.Je vais être contraire ici et dire qu'il n'est pas nécessaire pour
auto const &
dans une gamme à base de boucle. Dites-moi si vous pensez que la fonction suivante est stupide (pas à ses fins, mais dans la façon dont il est écrit):Ici, l'auteur a créé un const référence à
v
à utiliser pour toutes les opérations qui ne modifient pas v. C'est stupide, à mon avis, et le même argument peut être faite pour l'utilisation deauto const &
que la variable dans une plage de base pour la boucle au lieu de simplementauto &
.const_iterator
dans une boucle for? Comment vous assurez-vous que vous ne modifiez pas les éléments d'origine à partir d'un conteneur lorsque vous effectuer une itération sur elle?const_iterator
, mais pas pour s'assurer que je n'ai pas modifier les éléments dans le conteneur. Je voudrais utiliserconst_iterator
parce que sinon il ne compile pas pour const conteneurs. Je n'ai pas besoinconst_iterator
pour s'assurer que je n'ai pas modifier des éléments dans un conteneur, parce que je n'écris pas de la boucle de corps si grand que leur but n'est pas évident au premier regard.const_iterator
? Laissez-moi deviner, le récipient qui vous itérateur sur, estconst
. Mais pourquoi est-ilconst
pour commencer? Quelque part, vous êtes à l'aide deconst
pour s'assurer que?const
de référence? Mais pourquoi?const
pour commencer? Si vous les rendre non-const, alors vous n'avez pas à recevoir des arguments parconst
de référence. En gros, je me demande pourquoi utiliserconst
à tous?const
? Et pourquoi?const
est comme les avantages de l'utilisation deprivate
/protected
dans les classes. Il évite des erreurs.SafePop()
est stupide seulement parce qu'il ne prend pas une référence àconst
en premier lieu. Mais en supposant que certains idiot patron a dit le programmeur "Cette fonction A pour cette signature, tout droit? Je ne m'inquiète pas si vous ne l'aimez pas!", ensuite, je dirais que le programmeur a fait un bon travail.v
, la mise en œuvre serait bien de l'OMI. Et si la boucle ne modifie jamais les objets qu'il parcourt, il me semble bon pour moi d'avoir une ref àconst
. Je vois votre point de si. La mienne est que la boucle représente une unité de code un peu comme la fonction, et au sein de l'unité il n'y a pas d'instruction qui ont besoin de modifier la valeur. Par conséquent, vous pouvez "marquer" l'ensemble de l'unitéconst
, comme vous le feriez avec unconst
de la fonction membre.const &
pour la gamme de base est stupide, parce que vous avez écrit une pertinence exemple imaginaire de imaginaire programmeur qui a fait quelque chose de stupide avec cv-qualification? ...OK, alorsconst
objet, tout comme unconst &
paramètre. Pourquoi pensez-vous que ce n'est pas utile? Je suis heureux que vous êtes un assez bon programmeur n'a pas besoin de l'erreur de compilation, mais sinon c'est vraiment une bonne sauvegarde et de l'indication de l'intention.