40 votes

Recyclage des variables de type référence - une nouvelle variable de référence est-elle créée à chaque boucle dans une boucle si elle y est déclarée ?

C'est le suivant :

MyObject myVariable;
for(int i = 0; i < objects.Length, i++){
  myVariable = objects[i];
  // do stuff...
}

plus efficace alors :

for(int i = 0; i < objects.Length, i++){
  MyObject myVariable = objects[i];
  // do stuff...
}

parce qu'une nouvelle variable pour contenir une référence n'est pas créée à chaque fois ? (ou le compilateur est-il assez intelligent pour utiliser la même variable)

(Si une nouvelle variable est créée, est-elle malloquée sur le tas ?)

79voto

StriplingWarrior Points 56276

Non, les "variables" existent presque uniquement pour le bien du programmeur. Vous ne créez pas de travail supplémentaire au moment de l'exécution en déclarant la variable dans la méthode.

En théorie, le compilateur réserve de l'espace sur la pile lorsqu'une méthode est appelée pour chaque variable déclarée dans cette méthode. Ainsi, la présence de cette variable dans la méthode serait plus importante que sa portée. Aucun espace n'est alloué sur le tas à moins que la fonction new est utilisé.

En pratique, le compilateur peut identifier des variables dont la portée est si courte qu'elles peuvent être stockées dans un registre du processeur au lieu de nécessiter de l'espace sur la pile. Par exemple :

var a = b[c];
a.ToString();
// never access "a" again.

... serait la même chose que :

b[c].ToString();

... parce que le compilateur reconnaît qu'il n'a besoin de stocker le résultat de b[c] que le temps d'appeler une méthode sur lui, et qu'il peut donc simplement utiliser un registre du CPU au lieu d'utiliser la mémoire.

Pour cette raison, en déclarant votre variable à l'intérieur de la boucle pourrait en fait provoquer l'allocation de la méthode moins l'espace de la pile pour la variable, en fonction du flux logique possible par la suite. Cependant, cela relève d'une micro-optimisation énorme qui n'a aucun sens pour la plupart des gens.

Mise à jour

Puisque certaines personnes semblent encore penser que déclarer une variable dans une boucle a un effet quelconque, je suppose que je dois fournir une preuve. Tapez les programmes suivants dans LINQPad.

int j;
for(int i = 0; i < 5; i++)
{
    j = i;
}

... et...

for(int i = 0; i < 5; i++)
{
    int j = i;
}

Exécutez le code, puis allez dans l'onglet IL pour voir le code IL généré. C'est la même chose pour ces deux programmes :

IL_0000:  ldc.i4.0    
IL_0001:  stloc.0     
IL_0002:  br.s        IL_0008
IL_0004:  ldloc.0     
IL_0005:  ldc.i4.1    
IL_0006:  add         
IL_0007:  stloc.0     
IL_0008:  ldloc.0     
IL_0009:  ldc.i4.5    
IL_000A:  blt.s       IL_0004

Il y a donc une preuve irréfutable que cela ne fera aucune différence au moment de la compilation. Vous obtiendrez exactement le même IL compilé pour les deux programmes.

1voto

Dennz Points 11

J'ai fait un benchmark du "problème" et je suis d'accord avec StriplingWarrior. Au moins, cela ne fait aucune différence en termes de vitesse.

long start = Time();
long end = Time();
Console.WriteLine("Benchmark Runtime: " + (end - start) + " Microseconds");

for(int k = 0; k < 5; k++)
{
    start = Time();
    int j;
    for (int i = 0; i < 900000000; i++)
    {
        j = i;
    }
    end = Time();
    Console.WriteLine("Benchmark 1: " + (end - start) + " Microseconds");
}

for (int k = 0; k < 5; k++)
{
    start = Time();
    for (int i = 0; i < 900000000; i++)
    {
        int j = i;
    }
    end = Time();
    Console.WriteLine("Benchmark 2: " + (end - start) + " Microseconds");
}

Résultats :

Benchmark Runtime: 1 Microseconds
Benchmark 1: 1730816 Microseconds
Benchmark 1: 1725885 Microseconds
Benchmark 1: 1725629 Microseconds
Benchmark 1: 1726052 Microseconds
Benchmark 1: 1726121 Microseconds
Benchmark 2: 1725843 Microseconds
Benchmark 2: 1725576 Microseconds
Benchmark 2: 1726233 Microseconds
Benchmark 2: 1725786 Microseconds
Benchmark 2: 1729965 Microseconds

-5voto

Krum110487 Points 471

En bref, oui.

Réponse longue, oui c'est plus rapide, mais à peine perceptible à moins d'être répété plusieurs fois :-)

Je ne suis pas sûr que le compilateur l'optimisera ou non, j'en doute cependant, et s'il le fait, tant mieux pour lui, vous devriez quand même l'écrire comme s'il ne le faisait pas, faites-en une habitude.

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