259 votes

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 de deux manières principales1, 2, 3, 4

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 articles, 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 un const?

456voto

Nawaz Points 148870

Si vous ne voulez pas modifier les éléments ainsi que voulez éviter de faire des copies, alors auto const & est le bon choix:

for (auto const &x : vec)

Celui qui vous propose d'utiliser auto & est faux. Les ignorer.

Voici un rappel:

  • Choisissez auto x quand vous voulez travailler avec des copies.
  • Choisissez auto &x quand vous voulez travailler avec des éléments d'origine et peut les modifier.
  • Choisissez auto const &x quand vous voulez travailler avec des éléments d'origine et de ne pas les modifier.

29voto

Mr.C64 Points 11681

Si vous avez un std::vector<int> ou std::vector<double>, alors il est acceptable d'utiliser auto (de la valeur de la copie) au lieu de const auto&, depuis la copie d'un int ou double n'est pas cher:

for (auto x : vec)
    ....

Mais si vous avez un std::vector<MyClass>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'utiliser const auto& pour éviter profonde des copies:

for (const auto & x : vec)
    ....

3voto

Andy Prowl Points 62121

Lorsque nous n'avons pas besoin de changer vec articles, Exemples suggèrent d'utiliser la première version.

Ensuite, ils donnent une mauvaise suggestion.

Pourquoi ils n'ont pas de proposer quelque chose qui const références

Parce qu'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'un int n'est pas cher, la création d'une copie est essentiellement équivalent à (si pas plus efficace que l') ayant une observation const &.

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 &.

1voto

Benjamin Lindley Points 51005

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):

long long SafePop(std::vector<uint32_t>& v)
{
    auto const& cv = v;
    long long n = -1;
    if (!cv.empty())
    {
        n = cv.back();
        v.pop_back();
    }
    return n;
}

Ici, l'auteur a créé un const référence à l' 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 de auto const & que la variable dans une plage de base pour la boucle au lieu de simplement en auto &.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X