array - foreach loop c++



Y a-t-il des frais généraux pour déclarer une variable dans une boucle?(C++) (9)

Cette question a déjà une réponse ici:

Je me demande simplement s'il y aurait une perte de vitesse ou d'efficacité si vous faisiez quelque chose comme ceci:

int i = 0;
while(i < 100)
{
    int var = 4;
    i++;
}

qui déclare int var cent fois. Il me semble qu'il y en aurait, mais je ne suis pas sûr. Serait-il plus pratique / plus rapide de le faire à la place:

int i = 0;
int var;
while(i < 100)
{
    var = 4;
    i++;
}

ou sont-ils les mêmes, dans le sens de la vitesse et de l'efficacité?

https://code.i-harness.com


Avec seulement deux variables, le compilateur attribuera probablement un registre pour les deux. Ces registres sont là de toute façon, donc cela ne prend pas de temps. Il y a 2 instructions d'écriture de registre et une instruction de lecture de registre dans les deux cas.


Ces jours-ci, il est préférable de le déclarer dans la boucle sauf s'il s'agit d'une constante car le compilateur sera en mesure de mieux optimiser le code (réduction de la portée variable).

EDIT: Cette réponse est pour la plupart obsolète maintenant. Avec la montée en puissance des compilateurs post-classiques, les cas où le compilateur ne peut pas le comprendre deviennent rares. Je peux toujours les construire mais la plupart des gens classeraient la construction comme un mauvais code.


J'ai déjà effectué des tests de performance et, à ma grande surprise, j'ai trouvé que le cas 1 était plus rapide! Je suppose que c'est peut-être parce que déclarer la variable à l'intérieur de la boucle réduit sa portée, donc elle est libérée plus tôt. Cependant, c'était il y a longtemps, sur un très vieux compilateur. Je suis sûr que les compilateurs modernes font un meilleur travail pour optimiser les différences, mais cela ne fait quand même pas de mal de garder votre portée variable aussi courte que possible.


Je pense que la plupart des réponses manquent un point important à considérer qui est: «Est-ce clair» et évidemment de toute la discussion le fait est; non ce n'est pas. Je suggère dans la plupart des codes de boucle que l'efficacité est à peu près un problème (sauf si vous calculez pour un atterrisseur mars), donc la seule question est ce qui semble plus raisonnable et lisible et maintenable - dans ce cas, je vous recommande de déclarer la variable avant et en dehors de la boucle - cela le rend plus clair. Alors les gens comme vous et moi ne prendraient même pas la peine de perdre du temps à vérifier en ligne pour voir si c'est valide ou non.


La plupart des compilateurs modernes optimiseront cela pour vous. Cela étant dit, j'utiliserais votre premier exemple car je le trouve plus lisible.


La seule façon d'être sûr est de les chronométrer. Mais la différence, s'il y en a une, sera microscopique, vous aurez donc besoin d'une grande boucle de synchronisation.

Plus précisément, le premier est un meilleur style car il initialise la variable var, tandis que l'autre la laisse non initialisée. Ceci et la directive que l'on devrait définir des variables aussi près que possible de leur point d'utilisation signifie que la première forme devrait normalement être préférée.


Pour les types primitifs et les types POD, cela ne fait aucune différence. Le compilateur alloue l'espace de pile pour la variable au début de la fonction et la libère lorsque la fonction retourne dans les deux cas.

Pour les types de classes non-POD qui ont des constructeurs non-triviaux, cela fera une différence - dans ce cas, mettre la variable en dehors de la boucle n'appellera le constructeur et le destructeur qu'une fois et l'opérateur d'assignation à chaque itération, loop appellera le constructeur et le destructeur pour chaque itération de la boucle. Selon ce que font le constructeur, le destructeur et l'opérateur d'affectation de la classe, cela peut être souhaitable ou non.


Pour un type intégré, il n'y aura probablement aucune différence entre les deux styles (probablement jusqu'au code généré).

Cependant, si la variable est une classe avec un constructeur / destructeur non trivial, il pourrait bien y avoir une différence majeure dans le coût d'exécution. Je placerais généralement la variable à l'intérieur de la boucle (pour garder la portée aussi petite que possible), mais si cela s'avère avoir un impact sur la performance, je chercherais à déplacer la variable de classe en dehors de la portée de la boucle. Cependant, faire cela nécessite une analyse supplémentaire car la sémantique du chemin d'ode peut changer, donc ceci ne peut être fait que si la sémantique le permet.

Une classe RAII pourrait avoir besoin de ce comportement. Par exemple, une classe qui gère la durée de vie des accès aux fichiers peut devoir être créée et détruite à chaque itération de boucle pour gérer correctement l'accès aux fichiers.

Supposons que vous ayez une classe LockMgr qui acquiert une section critique quand elle est construite et la libère lorsqu'elle est détruite:

while (i< 100) {
    LockMgr lock( myCriticalSection); // acquires a critical section at start of
                                      //    each loop iteration

    // do stuff...

}   // critical section is released at end of each loop iteration

est assez différent de:

LockMgr lock( myCriticalSection);
while (i< 100) {

    // do stuff...

}

#include <stdio.h>
int main()
{
    for(int i = 0; i < 10; i++)
    {
        int test;
        if(i == 0)
            test = 100;
        printf("%d\n", test);
    }
}

Le code ci-dessus imprime toujours 10 fois 10, ce qui signifie que la variable locale à l'intérieur de la boucle n'est allouée qu'une seule fois par appel de fonction.





variable-declaration