2012-04-14 21 views
32

El siguiente código crea un objeto en la pila:Creación de objetos en la pila/pila?

Object o; 

Al crear un objeto en el montón que se puede utilizar:

Object* o; 

o = new Object(); 

en lugar de:

Object* o = new Object(); 

Cuando nos separamos la creación de objetos del montón sobre dos líneas y llamar al constructor en la segunda línea (o = new object()), ¿significa esto en la primera línea (Object* o) ¿el puntero fue creado en la pila? Entonces Object o pone el objeto en la pila, mientras que Object* o pone el puntero a un objeto futuro en la pila?

Mi segunda pregunta es si las dos líneas de código se llamaron fuera de una clase. Recientemente leí (Global memory management in C in stack or heap?) que las variables globales no están contenidas en la pila/pila pero en realidad son otra parte de la memoria. Si este es el caso, ¿crearía Object* o un puntero que se ubicaría en esta otra parte de la memoria y apunta al objeto montón?

+0

Esos dos * probablemente * optimizarán a la misma cosa, creo. – Ryan

+15

El _pointer_ siempre se crea en la pila. – leftaroundabout

+1

Sería el segundo @leftaroundabout, y llegaría más lejos: todas las variables declaradas en un bloque se crean en la pila; el objeto completo para el primer ejemplo y el puntero al objeto en el segundo. –

Respuesta

72

En realidad, ni declaración dice nada acerca de montón o pila:

Object o; 

crea un objeto con almacenamiento automático lo que significa que la ubicación de almacenamiento está determinada por el contexto en el que se declara el objeto: Si el código está en una función, esta es la pila de llamadas. Pero la línea también podría ser un miembro de la clase o, como habrás notado, fuera de una función/clase.

Para ilustrar por qué esto es diferente:

struct Foo { 
    Object o; 
}; 

Foo* pf = new Foo(); 

Ahora el objeto pf->o se crea en el montón, no en la pila, a pesar de que (o más bien, porque) que tiene almacenamiento automático.

Por el contrario,

Object* p; 

simplemente declara un puntero, nada más. El puntero no se puede distinguir de ningún otro objeto: tiene almacenamiento automático. Además, la expresión de inicialización no tiene ningún efecto en el almacenamiento variable.

Lo que señala el puntero es una cuestión completamente diferente. Puede ser un objeto asignado en el montón (usando new por ejemplo) o podría apuntar a otro objeto asignado automáticamente. Considere:

Object o; 
Object* p = &o; 
+1

¿Podría explicar qué quiere decir con "almacenamiento automático"? Además, ¿cuál sería la diferencia entre Foo pf = new Foo(); y Foo * pf = new Foo(); ? – user997112

+8

cuál sería la diferencia entre Foo pf = new Foo(); y Foo * pf = new Foo(); - El segundo compilaría, mientras que el primero no? – dasblinkenlight

+0

¿Porque solo podemos usar punteros con respecto a la asignación de montón? – user997112

3

Los dos formularios son iguales con una excepción: temporalmente, el nuevo (Object *) tiene un valor indefinido cuando la creación y la asignación son independientes. El compilador puede combinarlos nuevamente, ya que el puntero indefinido no es particularmente útil. Esto no se relaciona con las variables globales (a menos que la declaración sea global, en cuyo caso sigue siendo cierto para ambas formas).

1

En ambos ejemplos, las variables locales de tipo Object* se asignan en la pila. El compilador puede producir el mismo código en ambos fragmentos si no hay forma de que su programa detecte una diferencia.

El área de memoria para variables globales es la misma que el área de memoria para variables estáticas, no está en la pila ni en el montón. Puede colocar variables en esa área al declararlas static dentro de la función. La consecuencia de esto es que la instancia se convierte en compartida entre invocaciones simultáneas de su función, por lo que debe considerar cuidadosamente la sincronización cuando utiliza estática.

Aquí está a link para una discusión sobre el diseño de la memoria de un programa en ejecución C.

1

A)

Object* o; 
o = new Object(); 

`` B)

Object* o = new Object(); 

creo que A y B no tiene ninguna diferencia. En ambos casos, o es un puntero a la clase Objeto. declaración new Object() crea un objeto de clase Object desde la memoria del montón. El enunciado de asignación asigna la dirección de la memoria asignada al puntero o.

Una cosa que me gustaría mencionar es que el tamaño de la memoria asignada desde el montón es siempre el tamaño de (Objeto) no el tamaño de (Objeto) + tamaño de (nulo *).

6

C++ ofrece tres maneras diferentes para crear objetos:

  1. Pila de base, tales como objetos temporales
  2. Montón de base mediante el uso de nueva
  3. asignación de memoria estática como variables globales y Namespace alcance objetos

Tenga en cuenta su caso,

Object* o; 
o = new Object(); 

y:

Object* o = new Object(); 

Ambas formas son los mismos. Esto significa que una variable de puntero o se crea en la pila (suponga que sus variables no pertenecen a la categoría 3 anterior) y apunta a una memoria en el montón, que contiene el objeto.