2012-01-14 10 views
6

Estoy leyendo un libro que menciona esteasignación de almacenamiento para las variables const

Si el compilador conoce cada uso de la const, no es necesario asignar espacio para sostenerlo. Por ejemplo:

  1. const int c1=1;
  2. const int c3=my_f(3);
  3. extern const int c4;

Dado que los valores de C3 y C4 no son conocidos como tiempo de compilación, el almacenamiento hay que calcular para c3 y c4.

No entendí nada de esto. Mis dudas son:

¿Qué significa tenencia aquí? ¿No sería necesario almacenar todo en la memoria? Para c1, ¿no tendremos ninguna asignación de almacenamiento?

Por favor, aclare mis dudas.

Gracias.

+1

¿Qué pasó con 'c2'? –

Respuesta

4

c1 es diferente de las otras dos constantes en que se inicializa con un valor literal . Esto permite que el compilador puesto que el valor de todo el mundo se utiliza la constante, así:

int x = z + c1; 

pueden ser reemplazados por

int x = z + 1; 

Esto significa que el compilador no necesita asignar espacio y almacenar 1 en ella.

c3 y c4 son diferentes: uno se calcula utilizando una función y el otro se suministra desde una unidad de compilación diferente. Esto significa que el compilador ya no puede realizar la sustitución de la manera que podría con c1: los valores de c3 y c4 no son conocidos por el compilador. Por lo tanto, el compilador genera código para

int x = z + c4; 

de la misma manera como si c4 se almacena una variable en algún lugar de la memoria. Dado que en este caso c4 es una constante externa, el enlazador resolverá su ubicación y completará la información que falta en el compilador (es decir, la dirección de c4) para completar el programa y estar listo para ejecutarse.

+0

gracias por responder, pero eso no quiere decir que cada vez que una variable definida como una constante y se inicializa con un literal, actúa como una macro y en cualquier parte del programa se utiliza el compilador justs reemplaza la variable con valor? –

+1

@Leoheart El compilador * permite * hacer ese reemplazo, y la mayoría de los compiladores lo hacen. Pero hasta donde yo sé, los compiladores no tienen que constar "en línea" declaradas: el estándar les permite hacer cualquier cosa.Además, puede tomar una dirección de una constante declarada, en cuyo caso el compilador la coloca en la memoria además de marcarla en los lugares donde se usa. – dasblinkenlight

+0

Entendido. Gracias. –

1

Como una expresión constante integral, el compilador tiene todo el derecho a usar plegado constante para eliminarlo del programa. Esto solo no es cierto si tomas su dirección. Además, un compilador optimizador moderno puede emplear LTO, alineación y plegado constante para hacer lo mismo con c3 y c4, si es posible.

Si no toma la dirección de una variable, el compilador no tiene obligación de asignarla si puede generar código con resultados equivalentes, bajo la regla de si.

Editar: plegamiento constante es donde el compilador evalúa las expresiones en tiempo de compilación en lugar de en tiempo de ejecución. Por ejemplo, puede hacer legalmente int x[3 + 4]; donde 3 + 4 se evalúa en tiempo de compilación. Algunos ejemplos, específicamente los que involucran ICE, tienen un mandato estándar, pero la implementación puede realizar más si es posible. LTO es Link Time Optimization, que es donde el compilador realiza optimizaciones en las unidades de traducción cuando están vinculadas entre sí.

Esto significa que el compilador puede inline el cuerpo de my_f, y luego (en función del cuerpo) constante doblarla fuera para hacer c3 una expresión constante, y luego pliegue constante en donde se utiliza y no asignarlo. Para c4, LTO podría arrojar el valor de c4 como una expresión constante, en cuyo caso también se puede plegar y eliminar constantemente.

en C++ 11 hay constexpr funciones que permiten mucho más que hacer en esta región.

+0

Lo siento, no puedo entender tu respuesta también. ¿Qué es el plegado constante y LTO? –

+0

Lo tengo. Gracias. –

+0

Una última pregunta: ¿significa eso que una variable definida como const e inicializada con un literal, actúa como una macro y donde sea que esté en el programa el jitter del compilador reemplaza la variable con el valor? –

2

Const tiene 2 usos - sustitución de macros (expresiones constantes) y los datos inmutables.

Esta afirmación:

const int c1=1; 

es esencialmente una versión de tipo seguro de esto:

#define c1 1 

De tal manera que este código:

int foo = c1; 

podría simplemente ser compilado como:

int foo = 1; 

Cuál es más eficiente.

Por otro lado, esto:

const int c3=my_f(3); 

está siendo utilizado como una c3 inmutable. Es probable que exista en la memoria, pero no puede modificarlo. Básicamente es una versión más segura de int c3=my_f(3);.

Para ilustrar esto:

int a1[c1]; 
int a2[c3]; 

a1 es válida, ya que el compilador puede deducir a1 a ser una expresión constante. a2 no lo es, ya que mientras c3 es const, puede que no se conozca en tiempo de compilación.

C++ 11 agrega la palabra clave constexpr que es similar a const, aunque es más estricta que const. Solo c1 y c2 podrían ser constexpr. c3 también podría serlo, aunque requeriría que my_f también lo esté.

Cuestiones relacionadas