2009-10-21 12 views
32

So che la marcatura dei parametri delle stringhe come const può fare un'enorme differenza di prestazioni, ma per quanto riguarda i tipi ordinali? Guadagno qualcosa rendendoli const?Ci sono dei vantaggi nell'usare i parametri const con un tipo ordinale?

ho sempre usato const parametri durante la manipolazione stringhe, ma mai per Integer, Pointer, istanze di classi, ecc

Quando si utilizza const spesso devo creare variabili temporanee aggiuntive, che sostituiscono l'ormai protetti dalla scrittura parametri, quindi mi chiedo: ottengo qualcosa dal contrassegnare i parametri ordinali come const?

risposta

43

È necessario comprendere il motivo, per evitare la "programmazione settoriale del carico". Contrassegnare le stringhe come const fa una differenza di prestazioni perché non è più necessario utilizzare un incremento interlocked e decrementare il refcount sulla stringa, un'operazione che diventa effettivamente più costosa, non meno, con il passare del tempo perché più core significa più lavoro che deve essere fatto per mantenere sincronizzate le operazioni atomiche. Questo è sicuro da fare poiché il compilatore impone il vincolo "questa variabile non verrà modificata".

Per gli ordinali, che di solito sono 4 byte o meno, non si ottiene alcun guadagno in termini di prestazioni. L'utilizzo di const come ottimizzazione funziona solo quando si utilizzano tipi di valore superiori a 4 byte, ad esempio matrici o record o tipi conteggiati di riferimento come stringhe e interfacce.

Tuttavia, c'è un altro importante vantaggio: la leggibilità del codice. Se passi qualcosa come const e non fa alcuna differenza per il compilatore, può ancora fare la differenza per tu, dal momento che puoi leggere il codice e vedere che l'intenzione era di farlo non essere modificato. Questo può essere significativo se non hai visto il codice prima (qualcuno l'ha scritto) o se torni indietro dopo molto tempo e non ricordi esattamente cosa stavi pensando quando lo hai scritto originariamente.

+0

+1 sicuramente una spiegazione più soddisfacente della mia stessa – jpfollenius

+13

Il tuo primo paragrafo è sbagliato per quanto riguarda le stringhe. Le stringhe vengono sempre passate come rappresentazione del puntatore a quattro byte. 'Const' sopprime il codice nel prologo ed epilogo della funzione che aggiorna il conteggio dei riferimenti della stringa. Lo stesso vale per i parametri di interfaccia e gli array dinamici. Allo stesso modo, i record vengono passati come puntatori. 'Const' semplicemente sopprime il codice del prologo che copia il record nello stack locale della funzione. In altre parole, 'const' ha * nessun effetto * sul lato * caller * di una funzione. Influisce solo sul destinatario della chiamata. –

+2

@Rob: Bummer che i commenti non possono essere modificati. È facile interpretare erroneamente il tuo commento come se dicessi che i record vengono sempre passati come puntatori. –

8

La dichiarazione dei tipi ordinali const non fa alcuna differenza in quanto vengono comunque copiati (call-by-value), pertanto eventuali modifiche apportate alla variabile non influiscono sulla variabile originale.

IMHO che dichiara i tipi ordinali const non ha senso e, come dici tu, richiede di introdurre spesso variabili locali.

+2

Craig ha un punto valido. C'è una buona ragione per dichiarare un ordinale come const; non solo per motivi di prestazioni. –

16

Non è possibile trattarli accidentalmente come i parametri var e compilare il codice. Quindi rende chiare le tue intenzioni.

+3

Buon punto, ma non è sufficiente NON specificare un parametro var per rendere chiara la propria intenzione? – jpfollenius

+2

Smasher, il compilatore non distingue tra var e la convenzione di default in quanto ciò che è permesso fare con l'argomento nel metodo. –

+1

Anche se al momento sembra chiaro che si tratta di un valore che non si intende modificare, potrebbe non essere sei mesi più tardi quando si ritorna a esso, o quando un programmatore di manutenzione deve controllare il proprio codice. –

1

Dipende da quanto è complessa la routine e da come viene utilizzata. Se viene utilizzato in molti luoghi e richiesto che il valore rimanga lo stesso, dichiararlo come "const" per renderlo libero e sicuro. Per il tipo di stringa, c'era un bug (per Delphi 7 che stump su di esso) che causa il danneggiamento della memoria se si dichiara come "const".Qui di seguito è codici di esempio

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

C'è un enorme miglioramento della velocità utilizzando Const con le stringhe:

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; 

default: 443 const: 320 var: 325

default: 444 const: 303 var : 310

valore predefinito: 444 const: 302 var: 305

Stessa cosa con numeri interi:

default: 142 const: 13 var: 14

interessante notare, però, a 64-bit non sembra esserci quasi nessuna differenza con le stringhe (modalità predefinita è solo un po 'più lento const):

predefinito: 352 const: 313 var: 314

Problemi correlati