2009-10-21 7 views
32

Je sais que les paramètres de chaîne de marquage const peuvent faire une énorme différence de performance, mais qu'en est-il des types ordinaux? Est-ce que je gagne quelque chose en les rendant const?Y a-t-il des avantages à utiliser des paramètres const avec un type ordinal?

J'ai toujours utilisé const paramètres lors de la manipulation des chaînes, mais jamais pour Integer, Pointer, instances de classe, etc.

Lorsque vous utilisez const Je dois souvent créer des variables temporaires supplémentaires, qui remplacent l'écriture protégés maintenant paramètres, donc je me demande: Dois-je gagner quelque chose de marquage des paramètres ordinaux const?

Répondre

43

Vous devez comprendre la raison, pour éviter la «programmation de la cargaison-culte». Marquer des chaînes comme const fait une différence de performance car vous n'avez plus besoin d'utiliser un incrément et une décrémentation du refcount sur la chaîne, une opération qui devient plus chère, pas moins, au fil du temps car plus de cœurs signifie plus de travail cela doit être fait pour synchroniser les opérations atomiques. Ceci est sûr car le compilateur applique la contrainte "cette variable ne sera pas modifiée".

Pour les ordinaux, qui sont généralement de 4 octets ou moins, il n'y a pas de gain de performance à obtenir. L'utilisation de const comme optimisation ne fonctionne que lorsque vous utilisez des types de valeur supérieurs à 4 octets, tels que des tableaux ou des enregistrements, ou des types comptés par référence tels que des chaînes et des interfaces.

Cependant, il existe un autre avantage important: la lisibilité du code. Si vous passez quelque chose comme const et cela ne fait aucune différence pour le compilateur, il peut encore faire la différence à vous, puisque vous pouvez lire le code et voir que l'intention de cela était de ne pas être modifié. Cela peut être important si vous n'avez pas vu le code auparavant (quelqu'un d'autre l'a écrit) ou si vous y revenez après une longue période et ne vous souvenez pas exactement de ce que vous pensiez quand vous l'avez écrit.

+0

+1 certainement une explication plus satisfaisante que la mienne – jpfollenius

+13

Votre premier paragraphe est faux en ce qui concerne les chaînes. Les chaînes sont toujours passées en tant que leur représentation de pointeur de quatre octets. 'Const' supprime le code dans le prologue et l'épilogue de la fonction qui met à jour le nombre de références de la chaîne. Il en va de même pour les paramètres d'interface et les tableaux dynamiques. De même, les enregistrements sont passés en tant que pointeurs. 'Const' supprime simplement le code prologue qui copie l'enregistrement sur la pile locale de la fonction. En d'autres termes, 'const' n'a * aucun effet * sur le côté * appelant * d'une fonction. Cela affecte uniquement le destinataire de l'appel. –

+2

@Rob: Bummer que les commentaires ne peuvent pas être modifiés. Il est facile de mal interpréter votre commentaire comme si vous disiez que les enregistrements sont toujours transmis comme des pointeurs. –

8

La déclaration des types ordinaux const ne fait aucune différence car ils sont copiés de toute façon (appel par valeur), de sorte que les modifications apportées à la variable n'affectent pas la variable d'origine. À mon avis, déclarer constinal types const n'a aucun sens et comme vous le dites vous oblige à introduire des variables locales souvent.

+2

Craig a un point valable. Il y a une bonne raison de déclarer un ordinal comme const; juste pas pour des raisons de performance. –

16

Vous ne pouvez pas les traiter accidentellement comme des paramètres var et compiler votre code. Donc, cela rend vos intentions claires.

+3

Bon point, mais ne suffit-il pas de spécifier un paramètre var pour rendre son intention claire? – jpfollenius

+2

Smasher, le compilateur ne fait pas de distinction entre var et la convention par défaut dans la mesure où ce que vous êtes autorisé à faire avec l'argument dans la méthode. –

+1

Même s'il semble clair pour l'instant qu'il s'agit d'une valeur que vous n'avez pas l'intention de modifier, il se peut que six mois plus tard, vous y reveniez ou qu'un programmeur de maintenance consulte votre code. –

1

Cela dépend de la complexité de votre routine et de son utilisation. S'il est utilisé plusieurs fois et que la valeur reste la même, déclarez-la comme "const" pour la rendre claire et sûre. Pour le type de chaîne, il y avait un bogue (pour Delphi 7 comme je le soutiens) qui provoque la corruption de la mémoire si déclaré comme "const".Ci-dessous les codes échantillons

type 
    TFoo = class 
    private 
    FStr: string; 
    public 
    procedure DoFoo(const AStr: string); 
    begin 
     FStr := AStr; //the trouble code 1 
     ...... 
    end; 
    procedure DoFoo2; 
    begin 
     ..... 
     DoFoo(FStr); //the trouble code 2 
    end; 
    end; 
0

Il y a une énorme amélioration de la vitesse à l'aide Const avec des cordes:

function test(k: string): string; 
begin 
    Result := k; 
end; 

function test2(Const k: string): string; 
begin 
    Result := k; 
end; 

function test3(Var k: string): string; 
begin 
    Result := k; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
Var a: Integer; 
    s,b: string; 
    x: Int64; 
begin 
    s := 'jkdfjklf lkjj3i2ej39ijkl jkl2eje23 io3je32 e832 eu283 89389e3jio3 j938j 839 d983j9'; 

    PerfTimerInit; 
    for a := 1 to 10000000 do 
    b := test(s); 
    x := PerfTimerStopMS; 
    Memo1.Lines.Add('default: '+x.ToString); 

    PerfTimerInit; 
    for a := 1 to 10000000 do 
    b := test2(s); 
    x := PerfTimerStopMS; 
    Memo1.Lines.Add('const: '+x.ToString); 

    PerfTimerInit; 
    for a := 1 to 10000000 do 
    b := test3(s); 
    x := PerfTimerStopMS; 
    Memo1.Lines.Add('var: '+x.ToString); 
end; 

par défaut: 443 const: 320 var: 325

par défaut: 444 const: 303 var : 310

défaut: 444 const: 302 var: 305

Même avec Entiers:

par défaut: 142 const: 13 var: 14

Fait intéressant, 64 bits, il semble y avoir presque pas de différence avec les chaînes (mode par défaut est seulement un peu plus lent que const):

par défaut: 352 const: 313 var: 314

Questions connexes