2012-06-12 15 views
15

¿Qué diferencia hace cuando uso un parámetro const en un procedimiento?¿Qué diferencia hace cuando uso "const" en el parámetro de un procedimiento?

Tome el siguiente procedimiento, por ejemplo:

procedure DoSomething(Sender: TObject; const Text: String; var Reply: String); 
begin 
    //Text is read-only and Reply will be passed back wherever DoSomething() was called 
    Reply:= Text; 
end; 

El parámetro Text: String tiene el prefijo const de manera que (por lo que yo sé), se hace una copia del valor y se utiliza - y es de sólo lectura . Lo que me preguntaba es ¿cómo afecta esto a la aplicación de forma diferente que si no pusiera const allí? Tal vez un truco de rendimiento?

+1

Respondido aquí? http://stackoverflow.com/a/1601124/496736 –

+2

En la mayoría de los casos, creo que la principal ventaja de marcar cuidadosamente todos los parámetros de entrada solo como 'const' es que usted, el programador, obtendrá una ayuda adicional para evitar la tontería loco. –

+1

@Andreas Lo irritante es que el 'const' debe incluirse tanto en la interfaz como en la implementación. Esta es un área donde C++ vence a Delphi. –

Respuesta

22

En cuanto a los estados: documentation

". El uso de const permite al compilador para optimizar el código para estructurado - y de tipo cadena de parámetros También proporciona una salvaguardia contra el que pasa sin querer un parámetro por referencia a otra rutina"

En el caso de una cadena, por ejemplo, la optimización significa que no hay recuento adicional al pasar como const. También pasa como const no significa que es una copia. A menudo pasa internamente como referencia porque el compilador no garantiza el acceso de escritura.

Algunos artículos muy interesantes para entender completamente lo que está pasando bajo el capó:

http://delphitools.info/2010/07/28/all-hail-the-const-parameters

http://vcldeveloper.com/articles/different-function-parameter-modifiers-in-delphi

Editar:

Un simple ejemplo para mostrar que const puede provocar pase por referencia internamente:

program Project1; 

{$APPTYPE CONSOLE} 

type 
    PMyRecord = ^TMyRecord; 
    TMyRecord = record 
    Value1: Cardinal; 
    Value2: Cardinal; 
    end; 

procedure PassAsConst(const r: TMyRecord); 
begin 
    PMyRecord(@r).Value1 := 3333; 
    PMyRecord(@r).Value2 := 4444; 
end; 

procedure PassByVal(r: TMyRecord); 
begin 
    PMyRecord(@r).Value1 := 3333; 
    PMyRecord(@r).Value2 := 4444; 
end; 

var 
    r: TMyRecord; 
begin 
    r.Value1 := 1111; 
    r.Value2 := 2222; 
    PassByVal(r); 
    Writeln(r.Value1); 
    Writeln(r.Value2); 

    PassAsConst(r); 
    Writeln(r.Value1); 
    Writeln(r.Value2); 

    Readln; 
end. 
+3

FWIW: para saber cómo ** pasó **, no importa si un parámetro es const o no. Si no está explícitamente declarado 'var' o' out', será ** pasado ** igual para const o non-const. Generalmente, los elementos más grandes que el tamaño del registro (digamos, 32 bits) serán ** pasados ​​** por referencia, sin importar si son const o no. La única diferencia entre const y non-const es que para non-const, el código oculto se inserta al inicio y copia el elemento al almacenamiento local. Para const, solo se permiten las referencias de lectura, por lo que este código de copiado falta y la referencia aprobada se usa directamente. –

6

Cuando no tiene el prefijo const, el compilador tiene que suponer que va a cambiar el parámetro. Eso significa copiarlo y configurar un intento oculto ... finalmente para deshacerse de la variable de cadena local, por lo que a veces la const puede producir una mejora significativa en el rendimiento. También hace que el código generado sea más pequeño.

+0

Debo añadir que esto es cierto a partir de Delphi 2007 - el más nuevo que he instalado. El compilador más avanzado podría detectar que un parámetro no se usaba de hecho como una variable incluso sin el prefijo const y no se copiaba, pero esos tipos de optimizaciones históricamente no han sido el foco del equipo de Delphi R & D. –

+0

Es cierto en todas las versiones de Delphi que conocen los parámetros de const, es decir, mucho antes de D2007: no es necesario copiar estructuras, si se pasaron por referencia (esto depende de su tamaño), al almacenamiento local y no es necesario hacer recuento de referencias. –

1

Además de las respuestas anteriores de eficiencia al usar un const (es decir el compilador no necesita copiar la variable), si usa un const con un parámetro de interfaz, evita que se active el recuento de ref.

+0

Cuál es la razón de este comportamiento: http://qc.embarcadero.com/wc/qcmain.aspx?d=75036 –

+3

La falta de recuento de referencias es la misma para interfaces y cadenas. Lo que has dicho sobre las interfaces no es "además de" las cosas sobre las cadenas. La * variable * se copia todo el tiempo, pero copiarlas es barato ya que solo se copia el valor de un puntero, que a veces no es más que copiar un valor de un registro a otro. –

Cuestiones relacionadas