2010-03-26 25 views
12

Entiendo que una de las grandes ventajas de las constantes es que no tiene que pasar y actualizar el código donde esa constante se usa en todas partes. Eso es genial, pero digamos que no lo declaras explícitamente como una constante. ¿Qué beneficio (s) existe (n) para tomar una variable que SUCEDA que no se modifique y que sea constante, ahorrará en el procesamiento y/o tamaño del código ... etc.?Las ventajas de las constantes

Básicamente tengo un programa que el compilador dice que una variable en particular no se cambia y por lo tanto se puede declarar como constante, solo quería saber cuál sería el beneficio de agregar el calificador constante, si se hace No hay diferencia, entonces, hacer que ese cambio no agregue ningún valor y, por lo tanto, no pierda ningún momento (este mismo escenario ocurre en más de un lugar) retrocediendo y "arreglando" todas estas variables.

+0

Muchas buenas respuestas, gracias, estoy de acuerdo en que al declararlas como constantes hay un beneficio en cuanto al desarrollo, pero creo que estoy pensando en los beneficios en tiempo de ejecución, no necesariamente en el tiempo de compilación ... si eso hace sentido. – onaclov2000

+0

Los beneficios del tiempo de ejecución dependerán del compilador y máquina específicos en los que se compila y se ejecuta el programa; el lenguaje describe cómo deberían funcionar las cosas, no cómo se implementan las cosas. – jball

+1

La detección de errores en tiempo de compilación es mucho más importante que cualquier beneficio (mínimo) que pueda obtenerse en el tiempo de ejecución. Siempre puedes hacer que el código se ejecute más rápido comprando hardware más rápido, pero no puedes corregir el código de esa manera. Y si el código no es correcto, no tiene sentido ejecutarlo. –

Respuesta

17

Si declara que una variable es una constante, entonces el optimizador a menudo puede eliminarla a través de un "plegado constante", lo que acelera su programa y le ahorra espacio. Como un ejemplo, considere esto:

var int a = 5; 
const int b = 7; 
... 
c = process(a*b); 

El compilador terminar creando una instrucción para multiplicar una por 7, y pasar a que 'proceso', almacenando los resultados en c. Sin embargo, en este caso:

const int a = 5; 
const int b = 7; 
... 
c = process(a*b); 

El compilador simplemente pasará de 35 a procesar, y ni siquiera codificar la multiplican. Además, si el compilador sabe que el proceso no tiene efectos secundarios (es decir, es un cálculo simple), ni siquiera llamará al proceso. Simplemente configurará c como el valor de retorno del proceso (35), guardándole una llamada de función.

+0

Gran respuesta, este es el tipo de soluciones que estoy buscando, por ejemplo .. – onaclov2000

4

Marcar una variable como constante declara su intención como programador que este será un valor constante siempre que se acceda durante la ejecución del código. Considérelo como una forma de documentación que también hace que el compilador exija su diseño.

0

Las constantes son valores inmutables que se conocen en tiempo de compilación y no cambian durante la vida del programa.

Las constantes difieren de las variables de una manera significativa en que una vez que se ha asignado un valor a una constante, no puede modificarse posteriormente.

En tiempo de ejecución puede estar seguro de que el valor definido en una constante no cambiará y, por lo tanto, su programa no se romperá.

6

Mucho de esto depende de qué tan bueno sea su optimizador.

Un buen optimizador reemplazará referencias de referencias con valores literales durante la compilación. Esto ahorra ciclos de procesador ya que el código de máquina generado está trabajando con valores inmediatos en lugar de tener que cargar un valor desde la memoria.

Algunos optimizadores reconocerán que un valor no se modifica después de que se declara, y lo convierten en una constante para usted. No confíes en este comportamiento.

Además, siempre que sea posible, su código debe hacer cumplir las suposiciones que ha realizado durante el desarrollo. Si una "variable" nunca se debe cambiar, declararla como una constante ayudará a garantizar que ni usted ni ningún otro desarrollador que venga más tarde modifiquen sin darse cuenta una "constante".

3

Como señala, no puede obtener ningún beneficio directo al cambiar las variables invariables en constantes explícitas. Sin embargo, al analizar un programa, una comprobación que se realiza es mirar el punto de declaración de una variable al punto de referencia de la variable. Entonces las métricas como las variables a las que se accede antes de la declaración, o las que se configuran y reinician antes de la referencia, etc., pueden indicar probablemente errores.

Al declarar explícitamente las constantes como constantes, el compilador y las herramientas de análisis saben que no tiene intención de restablecer la variable en ningún momento.

Esto también es cierto para otros desarrolladores que trabajan con su código. Inadvertidamente pueden establecer una variable y es posible que no lo sepas. La declaración de constantes evitará estos tipos de errores.

1

Las constantes generalmente se almacenan en la memoria de solo lectura, lo que impide cambiarlas durante la ejecución y acceder a ellas puede ser más rápido, o al menos tan rápido como acceder a la memoria RAM.

+0

Supongo que esto depende del sistema en el que se está cargando este programa en particular, no estoy seguro de esto, pero parece interesante, lo investigaré de mi lado. – onaclov2000

2

Una de las ventajas es que si se trata de un valor constante, no lo cambiarás accidentalmente. La constante te impide complicar las cosas más tarde. Como variable, cualquiera podría venir y cambiarlo más tarde al actualizar el código.

Debe estar claro qué valores nunca pueden cambiar y qué valores pueden cambiar. Las constantes refuerzan tu intención.


ejemplo del mundo real desde mi juventud:

No teníamos un sistema incorporado en valor de PI en un sistema que estaba trabajando para que alguien crea una variable llamada PI y en algún lugar a lo largo del camino, alguien (yo) modifiqué ese valor a 3.14519 (o algo allí) en un procedimiento que escribí ... no la aproximación de pi 3.14159). Se había establecido en otra parte del código, y todo tipo de cálculos estaban apagados a partir de ese momento. Si ese PI hubiera sido una constante (se cambió más tarde, por supuesto), no habría podido cometer ese error ... al menos no fácilmente.

+0

Estoy completamente de acuerdo con su declaración, y veo el beneficio en ese sentido, solo estaba pensando más en las líneas del funcionamiento real del código cuando hice la pregunta. – onaclov2000

19

Si declara algo como una constante y accidentalmente intenta modificar su valor en el código, el compilador le informará sobre su error. Esta forma de comprobación de tipo estático es en realidad la razón principal para usar constantes.

+0

** ¡Esta es la razón más importante para las constantes! ** El rendimiento es bueno, pero no más y también depende en gran medida del compilador. Pero cuando partes del código asumen que algo siempre tiene el mismo valor y de repente cambia, ¡puede romper la ejecución! Así que usted decide qué es más importante el hecho de que bajo circunstancias muy específicas el código se ejecuta mínimamente más rápido o que el código se ejecuta correctamente en absoluto;) – ntziolis

+0

Supongo que esta respuesta está muy lejos de la práctica. Cuando codificas en la práctica y el compilador dice "const no se puede modificar" en el 99% de los casos, el accidente no fue una modificación involuntaria de la estructura sino que simplemente olvidaste cambiar el tipo;) – abimelex

2

Además de lo que ya se ha dicho, declarar la variable como una constante da más libertad para el optimizador. Puede eliminar la lectura de sus valores, puede eliminar la necesidad de crear una copia temporal, puede eliminar la variable en sí misma (esto es especialmente cierto para las constantes numéricas).

Otro gran caso de uso para las constantes son los objetos constantes. Tener un objeto constante (o dar una referencia a un objeto constante en una función) puede estar seguro de que su objeto no se modifica, y solo se permite llamar a los métodos (llamados métodos const) de ese objeto. Sin embargo, esto es cierto para C++, no estoy seguro si el mismo concepto también es válido en Ada.

2

Otra posibilidad, según el idioma, es que el compilador pueda realizar algunas optimizaciones en un entorno de subprocesos múltiples que de otro modo no sería posible. Al igual que si usted dice:

int b=x*f; 
int c=y*f; 

En un entorno multi-hilo, si f es una variable, el compilador puede tener que generar una recarga de f antes de la segunda operación. Si f es una constante y el compilador sabe que todavía está en el registro, no debería volver a cargarse.

3

Es posible que el compilador reduzca el tamaño del código.por ejemplo, en el paquete System encontrará (en una máquina x86)

type Bit_Order is (High_Order_First, Low_Order_First); 
Default_Bit_Order : constant Bit_Order := Low_Order_First; 

por lo que, dada

case System.Default_Bit_Order is 
    when System.High_Order_First => 
     -- Big-endian processing 
    when System.Low_Order_First => 
     -- Little-endian processing 
end case; 

el compilador puede eliminar por completo la rama 'equivocado', mientras que su código conserva su portabilidad. Con GNAT necesita usar una optimización no predeterminada para que esto suceda: -O2, creo.

Ambas ramas tienen que ser compilables: se trata de una optimización, no de procesamiento #ifdef.

2

Ciertamente, para un lenguaje como C y Ada, el compilador colocará el valor de la constante directamente en la instrucción del ensamblador, lo que significa que no será necesario intercambiar registros o leer desde la memoria. programa. Esto significa dos cosas: la principal es la velocidad (probablemente no tan notablemente en muchas aplicaciones, a menos que estén incorporadas) y la segunda es el uso de memoria (tanto del tamaño binario final del programa como de su huella de memoria de tiempo de ejecución).

Este comportamiento se reducirá al lenguaje y al compilador, ya que el lenguaje dictará cualquier suposición hecha por usted (el programador) y por lo tanto las limitaciones a la eficiencia del lenguaje; y el compilador porque su comportamiento podría cambiar desde tratar su constante como cualquier otra variable hasta preprocesar su código y optimizar la velocidad binaria y la huella tanto como sea posible.

En segundo lugar, como lo indica itsmatt y jball, le permite considerar lógicamente el elemento como un elemento de configuración constante en lugar de una 'variable'; especialmente en lenguajes de programación de nivel superior e idiomas interpretados.

2

Esto no es realmente una pregunta específica de Ada.

Los benifits generales de las constantes más variables:

  • errores de código Previene la formación de "constante" accidentalmente conseguir modificado.
  • Informa al compilador que puede suponer que el valor no cambiará al optimizar.

Ada benifits específicos:

  • Por las constantes numéricas, que no tienen que especificar un tipo (números con nombre). Si lo declaras de esta manera, será utilizable en cualquier expresión para ese tipo de número. Si usa una variable en su lugar, solo se puede usar en expresiones del tipo exacto de esa variable.

Ejemplo:

Seconds_Per_Minute : constant := 60; 
Secs_Per_Min  : Integer := 60; 

type Seconds_Offset is 0 .. Integer'last; --' 

Min1, Secs1 : Integer; 
Min2, Secs2 : Seconds_Offset; 

... 
--// Using the named number, both of these compile no problem. 
Secs1 := Min1 * Seconds_Per_Minute; 
Secs2 := Min2 * Seconds_Per_Minute; 

--// The second line here gives an error, since Integer is a 
--// different type than Seconds_Offset. 
Secs1 := Min1 * Secs_Per_Min; 
Secs2 := Min2 * Secs_Per_Min; 
+0

Errm, ya que Positivo es un subtipo de Entero no hay ningún error aquí; ¡y creo que tu intención era dividir en lugar de multiplicar! –

+0

@Simon - Guau, buenas capturas. Supongo que mi racha de código Ada escrito sin un error de compilación permanece, como siempre, en 0. Reformulado para mostrar lo que pretendía (espero). –

+0

Bueno, todavía estoy aprendiendo Ada, pero eso es muy interesante, puedes crear una variable constante sin un tipo ... ¡No lo sabía! – onaclov2000

2

Hay otro beneficio, apilar y tamaños de segmento de datos.

considerar:

function Recurser(i : Integer) return Integer is 
    ia : array(0..9) of Integer 
      := (1, 2, 3, 4, 5, 6, 7, 8, 9, 1000); 
    r : Integer; 
begin 
    if i = 0 then return 0; end if; 
    r := ia(i mod 10); 
    return r + Recurser(i - 1); 
end; 

Cada vez que la función recursivamente se crea una estructura de 320 bytes en la pila. Pero como el valor de a no cambia, la pila aumenta para mantener una variable constante. Esto puede ser muy importante en plataformas integradas con pilas pequeñas.

Las variables de nivel de paquete también aumentan el tamaño del segmento de datos. Reforzando tus requisitos de memoria.

Cuestiones relacionadas