2010-07-31 18 views
7

Cuando declaramos una variable, ¿la variable en sí misma consume memoria?¿Una variable en sí misma consume memoria?

class IHaveNothing 
{ 
} 

class IHaveNullFields 
{ 
    string @string = null; 
    StringBuilder @StringBuilder = null; 
} 

class Program 
{  
    static void Main(string[] args) 
    { 
     IHaveNothing nothing = new IHaveNothing(); 
     IHaveNullFields nullFields = new IHaveNullFields(); 
    } 
} 

¿La instancia nullFields consume más memoria que la instancia?

EDIT: ¿Qué hay de las variables locales nulas en oposición a los campos nulos de clase, también consumen memoria?

+1

Me gustaría agregar que la cantidad de memoria que está hablando es insignificante. Si los campos son nulos, solo habrá unos pocos bytes por instancia por miembro adicional. A menos que esté creando millones de instancias o cientos de campos, es poco probable que tenga un impacto en su proyecto. –

+0

pregunta confusa. Preguntas sobre las variables, pero parecen hablar sobre los campos. –

+1

@Hans: fields * are * variables. Una variable se define como * ubicación de almacenamiento *. Los campos son variables. Las variables locales son variables. Los elementos de matriz son variables. Si puede almacenar datos en él y cambiarlo, es una variable. –

Respuesta

9

Una variable es definido como una ubicación de almacenamiento. Entonces la pregunta es: ¿una ubicación de almacenamiento consume memoria?

Cuando lo dices de esa manera, parece obvio que la respuesta es sí. ¿Qué más haría una ubicación de almacenamiento que no sea consumir memoria?

No es tan simple como eso. Una variable local no puede consumir memoria en absoluto; una variable local podría ser registrada por la fluctuación de fase. En ese caso, no consumiría ni la pila ni la memoria del montón.

¿Por qué te importa? La forma en que el CLR administra la memoria para hacer ubicaciones de almacenamiento para las variables es un detalle de implementación. A menos que esté escribiendo un código inseguro, no tiene que preocuparse por ello.

+0

Deje que una colección de apartados postales sea un recuerdo. Cada celda de la memoria corresponde a una sola casilla de correos. Cada caja de oficina tiene una dirección única. Si "una variable se define como una ubicación de almacenamiento", significa que una variable es análoga a una casilla de la oficina postal o una dirección de una casilla de la oficina postal. – xport

+0

@xport: ¿Es un registro un apartado de correos en su analogía? ¿Cuál es su dirección? –

+0

P: "¿Qué otra cosa podría hacer una ubicación de almacenamiento aparte de consumir memoria? R: Utilizaría la memoria consumida antes mencionada para almacenar algo. – phoog

12

Sí, consumen el tamaño del puntero de la máquina (al menos).

+1

+1. Hace que cada instancia de esa clase en particular sea más grande por el tamaño del puntero. – Steven

3

IHaveNothing consume 1 byte. Consume un byte para garantizar que la ubicación de la variable sea única.

IHaveNullFields consume el tamaño de dos punteros.

variables locales nulas consumen el tamaño de un puntero.

Puede usar Marshall.SizeOf para determinar el tamaño de sus clases. Consulte http://msdn.microsoft.com/en-us/library/y3ybkfb3.aspx

+0

No, no puede usar Marshal.SizeOf para determinar el tamaño de sus clases, porque Marshal.SizeOf devuelve el tamaño de la clase después de ordenarla, no como está dispuesta en la memoria por el CLR. – dtb

+0

Tampoco estoy seguro de por qué una instancia de IHaveNothing debería consumir 1 byte. Todos los objetos CLR tienen un encabezado de objeto (¿8 bytes?), Así que dudo que haya necesidad de otro byte si la clase no tiene campos. – dtb

+2

Esto es pensamiento C++. Una clase de referencia * siempre * tiene la sobrecarga de los campos internos System.Object. –

2

Para los tipos de valor, la variable contiene el valor en sí, pero para los tipos de referencia, el objeto va al montón (el espacio de memoria administrada) y la variable contiene una referencia que apunta al inicio del bloque de memoria utilizado para sostener el objeto.

El tamaño del puntero lo determina su sistema, en un sistema de 32 bits, el puntero de referencia es de 4 bytes y para un sistema de 64 bits el puntero será de 8 bytes.

Como los tipos de referencia requieren esta sobrecarga por objeto, la recomendación es que para un tipo que probablemente creará muchas veces, como el tipo Point utilizado en cualquier programa de dibujo, debe hacer que los tipos de valor utilicen el struct palabra clave.

+0

Me han dicho anteriormente, y ahora estoy de acuerdo con esa crítica, que uno no debe hacer de algo un valor o tipo de referencia debido a dónde se almacenará o cuántos bytes ocupará (estos deben considerarse detalles de implementación de la CLI y no debe afectar el diseño de su programa); lo que importa es la diferente semántica de igualdad y copia de los tipos de valor y referencia. – stakx

+0

@stakx, existen algunas excepciones en los casos en que un tipo se utiliza con mucha frecuencia. Por ejemplo, las implementaciones de IEnumerator para la mayoría de las clases de colecciones BCL son tipos de valores mutables. Esto es por motivos de rendimiento, ya que las colecciones estándar se enumeran con frecuencia. Por supuesto, dado que la enumeración generalmente se realiza detrás de las escenas a través de foreach, esto generalmente evita que el usuario se encuentre en problemas. En general, sin embargo, es mejor usar clases, particularmente si el tipo va a ser mutable. Si planea crear un tipo de valor mutable, debe tener una muy buena razón. –

+0

Existen otras razones por las que también desearía usar tipos de valores inmutables además del rendimiento. El uso de un tipo de valor inmutable tiene algunos beneficios, Eric Lippert escribió una serie de once partes sobre inmutabilidad que bien vale la pena leer si tiene tiempo (aquí está la primera parte http://blogs.msdn.com/ericlippert/archive/2007 /11/13/immutability-in-c-part-one-kinds-of-immutability.aspx). – theburningmonk

Cuestiones relacionadas