Question

string strLine;//not constant
int index = 0;
while(index < strLine.length()){//strLine is not modified};

combien de fois strLine.length() sont évalués

devons-nous mettre l'utilisation nLength avec <=> attribué à <=> juste avant la boucle

Était-ce utile?

La solution

length sera évalué chaque fois que vous passerez dans la boucle. Toutefois, étant donné que O(1) est un temps constant (<=>), cela ne fait pas grande différence et l'ajout d'une variable pour stocker cette valeur aura probablement un effet négligeable. effet avec un petit impact sur la lisibilité du code (ainsi que de casser le code si la chaîne est modifiée).

Autres conseils

length () est défini dans les en-têtes inclus dans votre fichier source. Il peut donc être inséré en ligne par le compilateur. Ses appels internes peuvent également être insérés en ligne. Par conséquent, si le compilateur peut détecter que votre instance de chaîne n'est pas modifiée dans la boucle, il peut alors optimiser l'accès à la longueur d'une chaîne, de sorte qu'elle ne sera évaluée qu'une seule fois. Dans tous les cas, je ne pense pas que stocker la valeur de la longueur de la chaîne soit vraiment nécessaire. Peut-être que cela peut vous faire économiser des nanosecs, mais votre code sera plus gros et il y aura un risque lorsque vous déciderez de changer cette chaîne dans la boucle.

Chaque fois, il est appelé ... (chaque évaluation). Si vous ne changez pas la longueur de la chaîne, il vaut mieux utiliser une variable temporaire telle que:

string strLine;
int stringLength = strLine.length();
int index = 0;
while(index < stringLength);

Je pense qu'il y a une deuxième question qui se cache à l'intérieur de cela, et c'est & "quelle implémentation est plus claire? &";

Si, sémantiquement, vous voulez que la longueur de strLine ne change jamais dans le corps de la boucle, rendez-la évidente en attribuant une variable bien nommée. Je ferais même le const. Cela montre clairement aux autres programmeurs (et à vous-même) que la valeur de comparaison ne change jamais.

L’autre chose que cela permet de voir plus facilement quelle est cette valeur lorsque vous parcourez le code dans un débogueur. Le survol fonctionne mieux sur un local que sur un appel de fonction.

Dire, & "Laissons-le comme un appel de fonction; le compilateur l'optimisera " me semble une pessimisation prématurée. Même si length () est O (1), s'il n'est pas aligné (vous ne pouvez pas garantir que les optimisations ne sont pas désactivées), il s'agit toujours d'un appel de fonction non trivial. En utilisant une variable locale, vous clarifiez votre signification et vous obtenez une optimisation des performances éventuellement non triviale.

Faites ce qui rend votre intention plus claire.

strLine.length () sera évalué alors que (i < strLine.length ())

Cela dit, si la chaîne est constante, la plupart des compilateurs l'optimiseront (avec les paramètres appropriés).

Si vous allez utiliser une variable temporelle, utilisez un qualificatif const afin que le compilateur puisse ajouter des optimisations tout en sachant que la valeur ne changera pas:

string strLine;//not constant
int index = 0;
const int strLenght = strLine.Length();
while(index < strLine.length()){//strLine is not modified};

De toute façon, le compilateur lui-même effectue ces optimisations lorsqu’il accède quand même à la méthode Length ().

Edit: mon montage est un peu rouillé, mais je pense que l'évaluation n'a lieu qu'une fois. Étant donné ce code:

int main()
{
    std::string strLine="hello world";

    for (int i=0; i < strLine.length(); ++i)
    {
        std::cout << strLine[i] <<std::endl;
    }
}

Génère cet assemblage:

    for (int i=0; i < strLine.length(); ++i)
0040104A  cmp         dword ptr [esp+20h],esi 
0040104E  jbe         main+86h (401086h)

Mais pour ce code

 std::string strLine="hello world";
 const int strLength = strLine.length();
 for (int i=0; i < strLength ; ++i)
 {
    std::cout << strLine[i] <<std::endl;
 }

génère celui-ci:

   for (int i=0; i < strLength ; ++i)
0040104F  cmp         edi,esi 
00401051  jle         main+87h (401087h) 

Le même assemblage est généré si un qualificatif const n'est pas utilisé. Dans ce cas, cela ne fait aucune différence.

Essayé avec VSC ++ 2005

Comme indiqué, étant donné que la fonction string::length est probablement entièrement définie dans un en-tête et doit obligatoirement être O (1), il est presque certain de l'évaluer comme un simple accès membre et de s'inscrire dans votre code. Puisque vous ne déclarez pas la chaîne comme étant volatile, le compilateur est autorisé à imaginer qu’aucun code extérieur ne la modifiera, à optimiser l’appel sur un accès mémoire unique et à laisser la valeur dans un registre s’il découvre que c’est un bonne idée.

En récupérant vous-même et en mettant en cache la valeur, vous augmentez les chances que le compilateur puisse faire la même chose. Dans de nombreux cas, le compilateur ne générera même pas le code pour écrire la longueur de chaîne dans la pile et le laissera simplement dans un registre. Bien sûr, si vous appelez différentes fonctions que le compilateur ne peut pas insérer en ligne, la valeur devra alors être écrite dans la pile pour empêcher les appels de fonction de perturber le registre.

Puisque vous ne changez pas la chaîne, ne devriez-vous pas utiliser

const string strLine;

Simplement, car le compilateur obtient alors plus d'informations sur ce qui peut et ne peut pas changer - vous ne savez pas exactement à quel point un compilateur C ++ peut être intelligent, cependant.

strLine.length() sera évalué chaque fois que vous contournez la boucle.

Vous avez raison de dire qu'il serait plus efficace d'utiliser nLength, surtout si strLine est long.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top