Laisse faire ton compilateur, il sait ce qu’il fait :)
Ce qui est bien avec les compilateurs modernes, c’est qu’ils sont très bons pour optimiser le code à notre place. Un bon code est un code efficace mais simple, que le compilateur comprendra et analysera facilement. Le développeur pourra décider d’écrire un code « plus optimisé » si et seulement si le compilateur n’a pas réussi à produire quelque chose de satisfaisant. Mais il devrait quand même d’abord essayer de clarifier son code 😉
J’en ai encore fait l’expérience ces jours-ci en me demandant si un ranged-loop for (apparu en C++11) sur un tableau avait un overhead par rapport à un parcours classique avec un index de 0 à taille-1. Je suis donc aller sur Compiler Explorer et j’ai écrit ce petit code :
void f(int v);
constexpr int SIZE = 128;
int array[SIZE];
void g() {
for(auto& e : array) {
f(e);
}
}
void h() {
for(int i = 0; i < SIZE; ++i) {
auto& e = array[i];
f(e);
}
}
Je l'ai ensuite compilé avec GCC 7.2.1 pour ARM, puisque c'est la toolchain que j’utilise sur mon projet actuel. Avec l’optimisation à O2 ou O3, les codes assembleurs générés sont les mêmes. En revanche, une des versions est un poil meilleure en O1…. et ce n’est pas la version classique mais la version mode du ranged-loop for. Sans doute parce qu’il n’y a aucune ambiguïté sur le code : il s’agit bien de parcourir le tableau élément par élément. La différence est minime toutefois 😉
Voici ce que ça donne (les couleurs montrent la correspondance code source / code assembleur) :


Conclusion : laissez faire votre compilateur, il sait ce qu’il fait…. et sans doute bien mieux que vous !


