web-dev-qa-db-fra.com

Efficacité de boucle pour C++ 11 "const auto & i" versus "auto i"

En C++ 11, je peux parcourir un conteneur de la manière suivante:

for(auto i : vec){
   std::cout << i << std::endl;
}

Mais je sais que cela - inutilement, puisqu'il ne me faut que print les valeurs de vec - crée une copie de (EDIT: chaque élément de) vec, alors je pourrait faire:

for(auto &i : vec){
   std::cout << i << std::endl;
}

Mais je veux m'assurer que les valeurs de vec ne sont jamais modifiées et respectent const-correctness, ainsi je peux faire:

for(const auto &i : vec){
   std::cout << i << std::endl;
}

Ma question est donc la suivante: si j’ai seulement besoin de regarder les valeurs d’un conteneur, la dernière boucle (const auto &i) ne serait-elle pas toujours préférée en raison de l’efficacité accrue de ne pas disposer d’une copie supplémentaire de (EDIT: chaque élément de) vec?

J'ai un programme que je développe dans lequel je songe à apporter ce changement, car l'efficacité y est essentielle (la raison pour laquelle j'utilise le C++ à la première place).

48
user2052561

Oui. La même raison si vous ne lisez qu'un argument, vous définissez le paramètre const&.

T        // I'm copying this
T&       // I'm modifying this
const T& // I'm reading this

Ce sont vos "valeurs par défaut". Lorsque T est un type fondamental (intégré), vous revenez généralement à const T (pas de référence) pour la lecture, car une copie est moins chère qu'un alias.


J'ai un programme que je développe dans lequel j'envisage de faire ce changement, car l'efficacité y est essentielle

  1. Ne faites pas de changements aveugles. Un programme de travail est préférable à un programme rapide mais brisé. 
  2. La façon dont vous parcourez vos boucles ne fera probablement pas beaucoup de différence; vous faites une boucle pour une raison, n'est-ce pas? Le corps de votre boucle sera probablement le coupable.
  3. Si l'efficacité est cruciale, vous souhaitez utiliser un profiler pour rechercher les parties de votre programme qui sont réellement lentes, plutôt que de deviner si pourrait être lent. Voir n ° 2 pour savoir pourquoi votre proposition peut être fausse.
63
GManNickG

Imaginez si votre vecteur contient des chaînes. Longues ficelles. 5000 longues ficelles. Copiez-les inutilement et vous vous retrouverez avec une boucle bien écrite qui est terriblement inefficace.

Assurez-vous que votre code suit votre intention. Si vous n'avez pas besoin d'une copie à l'intérieur de la boucle, n'en faites pas.

Utilisez une référence & comme suggéré ci-dessus, ou des itérateurs.

0
Visiedo