2011-01-25 8 views

Respuesta

23

Un enum es un tipo definido por el usuario, no una variable.enum e = 2; es una mano corta para algo como esto enum : int { e = 2 } (es decir, una enumeración anónima con un miembro e), vea the documentation. Por definición, todos los miembros de una enumeración anónima se colocan en el alcance actual . Por lo tanto, e es un miembro de tipo ubicado en el ámbito actual, donde se comporta como como literal. immutable i = 2; por el contrario, en realidad crea una variable i de tipo int.

Esta diferencia tiene un par de consecuencias:

  • enum e no tendrá ninguna posición de memoria y sin dirección (es ningún valor-I), ya que ni un tipo ni sus miembros tienen una dirección. Es decir. no puede hacer algo como auto ptr = &e; (al igual que no puede hacer auto ptr = &2;). immutable i por otro lado es una variable normal (solo inmutable).
  • As discussed by Jonathan, variables de inmutables se pueden inicializar en tiempo de compilación o en tiempo de ejecución, mientras que un tipo (con todos sus miembros que definen el tipo) debe ser conocida en tiempo de compilación.
  • El compilador puede simplemente reemplazar todas las apariciones de e con 2. Para i, generalmente tiene que crear una ubicación de memoria (aunque un compilador de optimización podría evitar esto a veces). Por esta razón, se espera que la carga de trabajo durante la compilación para un enum sea algo menor, y el binario algo más pequeño.
  • Existe una diferencia sorprendente para las matrices. Para enum uint[2] E = [0, 1]; y immutable uint[2] I = [0, 1]; el acceso al enum, p. Ej. E[0], puede ser órdenes de magnitud más lentos que para la matriz immutable, p. I[0], especialmente cuando las matrices E y I crecen. Esto es así porque para una matriz immutable, es solo una búsqueda de matriz normal para, por ejemplo, una variable global . Para el enum, sin embargo, parece que el conjunto se crea cada vez antes de que se utilice, p. dentro de una función para un enum global (no lo haga pregúnteme, por qué, pero el compilador realmente parece simplemente reemplazar la apariencia con el valor en este caso, también). Nunca lo he intentado pero supongo que lo mismo se aplica a las cadenas enum y otros tipos no triviales.

En resumen: cuando se utiliza en tiempo de compilación constantes, normalmente tomar enum menos que esas constantes son matrices o que necesitan una ubicación de memoria por alguna otra razón.

+0

+1 Interesante ... gracias. – Mehrdad

8

las enumeraciones siempre se inicializan en el momento de la compilación. Por lo tanto, debe tener valores asignados que se pueden crear a través de CTFE (Compile Time Function Evaluation).

variables inmutables se pueden inicializar en tiempo de ejecución. Si una variable inmutable tiene una vida global (por lo tanto, es una variable de módulo o una clase estática o una variable local estática), debe inicializarse en tiempo de compilación o en tiempo de ejecución con un constructor estático (aunque las variables locales estáticas no pueden ser asignado con un constructor estático). Si una variable inmutable es una variable local no estática, entonces se inicializa en tiempo de ejecución (aunque si el valor es una constante, entonces el compilador podría optimizarlo e inicializarlo en tiempo de compilación). Por lo tanto, puede crear variables locales inmutables en tiempo de ejecución, a diferencia de las enumeraciones.

EDIT: Otro caso me olvidaba: las variables miembro inmutables deben o pueden inicializar directamente con CTFE o inicializar con una constructora inmutable. Si un miembro variable inmutable se inicializa directamente con CTFE, obviamente eso se hace en tiempo de compilación, mientras que la inicialización en un constructor inmutable se realiza en tiempo de ejecución.

+0

Sí. Porque esa no es una expresión CTFE válida. Actualmente no puedes usar 'new' con CTFE. No es tan avanzado todavía. –

+0

Espera, pero ¿cómo puedo hacer una instancia inmutable de una clase? – Mehrdad

+0

'new inmutable (Temp)()' está bien. Sin embargo, si se trata de una variable miembro, debe hacerse en un constructor inmutable. No se puede inicializar directamente una variable de miembro de clase inmutable, ya que la inicialización directa de una variable miembro debe hacerse con un valor generado por CTFE, y actualmente no puede usar 'new' con CTFE. Por lo tanto, declare 'this (/*...*/) inmutable {/*...*/}' e inicialice la variable miembro dentro de ella. –