¿Este tipo de memoria se asigna en el montón o en la pila?
-
06-07-2019 - |
Pregunta
En el contexto de C ++ (no es que importe):
class Foo{
private:
int x[100];
public:
Foo();
}
Lo que aprendí me dice que si creas una instancia de Foo así:
Foo bar = new Foo();
Luego, la matriz x se asigna en el montón, pero si creó una instancia de Foo así:
Foo bar;
Luego se crea en la pila.
No puedo encontrar recursos en línea para confirmar esto.
Solución
Dada una ligera modificación de su ejemplo:
class Foo{
private:
int x[100];
int *y;
public:
Foo()
{
y = new int[100];
}
~Foo()
{
delete[] y;
}
}
Ejemplo 1:
Foo *bar = new Foo();
- x e y están en el montón:
- sizeof (Foo *) se crea en la pila.
- sizeof (int) * 100 * 2 + sizeof (int *) está en el montón
Ejemplo 2:
Foo bar;
- x está en la pila e y está en el montón
- sizeof (int) * 100 está en la pila (x) + sizeof (int *)
- sizeof (int) * 100 está en el montón (y)
Los tamaños reales pueden diferir ligeramente debido a la alineación de clase / estructura dependiendo de su compilador y plataforma.
Otros consejos
Hablando estrictamente, de acuerdo con el estándar, el objeto no necesita existir en una pila o montón. El estándar define 3 tipos de 'duración de almacenamiento', pero no establece exactamente cómo se debe implementar el almacenamiento:
- duración del almacenamiento estático
- duración de almacenamiento automático
- duración del almacenamiento dinámico
La duración del almacenamiento automático se implementa típicamente (casi siempre) usando la pila.
La duración del almacenamiento dinámico generalmente se implementa usando el montón (en última instancia, a través de malloc ()
), aunque esto puede ser anulado incluso por el usuario del compilador.
La duración del almacenamiento estático es lo que normalmente se conoce como globales (o almacenamiento estático).
El estándar tiene esto que decir sobre estas cosas (los siguientes son extractos de varios bits de 3.7 - Duración del almacenamiento):
Duraciones de almacenamiento estático y automático están asociados con objetos introducidos por declaraciones (3.1) e implícitamente creado por la implementación (12.2). La duración del almacenamiento dinámico es asociado con objetos creados con operador nuevo (5.3.4).
...
Todos los objetos que no tienen dinámica la duración del almacenamiento ni son locales tienen duración del almacenamiento estático El almacenamiento porque estos objetos durarán por el duración del programa (3.6.2, 3.6.3).
...
Objetos locales declarados explícitamente auto o registrarse o no declarado explícitamente estático o externo tiene automático duración del almacenamiento El almacenamiento para estos objetos duran hasta que el bloque en que se crean salidas.
...
Los objetos se pueden crear dinámicamente durante la ejecución del programa (1.9), usando expresiones nuevas (5.3.4) y destruidas utilizando expresiones de eliminación (5.3.5). A C La implementación de + + proporciona acceso y gestión de almacenamiento dinámico a través de las funciones de asignación global operador nuevo y operador nuevo [] y las funciones de desasignación global operador eliminar y operador eliminar [].
...
La biblioteca proporciona valores predeterminados definiciones para la asignación global y funciones de desasignación. Algunos asignación global y desasignación las funciones son reemplazables (18.4.1)
Y finalmente (con respecto a la matriz en su clase de ejemplo):
3.7.4 Duración de los subobjetos [basic.stc.inherit]
La duración de almacenamiento de los subobjetos miembros, los subobjetos de la clase base y los elementos de la matriz es la de su completa objeto (1.8).
Un objeto de tipo Foo toma el tamaño de 100 ints almacenados en secuencia. Si lo crea en la pila, lo obtendrá todo en la pila. Si lo haces con nuevo, estará en el montón como parte del objeto.
Esto es parte de la especificación del lenguaje, no estoy seguro de cuál es su pregunta.
Sí, la matriz de miembros x
se creará en el montón si crea el objeto Foo
en el montón. Cuando asigna memoria dinámica para Foo
, está solicitando memoria de longitud sizeof (Foo)
(más posiblemente algo de sobrecarga de memoria, pero ignoremos eso por el momento), que en su código de muestra implica el tamaño de 100 int
s. Este tiene ser el caso para la vida útil de los objetos de tipo Foo
(y sus datos internos) para cruzar ámbitos.
Si no crea el objeto Foo
en el montón, y la matriz interna de Foo
no es un puntero al que asigna memoria con nuevo
en el constructor de Foo
, entonces esa matriz interna se creará en la pila. Nuevamente, este debe ser el caso para que la matriz se limpie automáticamente sin ninguna delete
s cuando finalice el alcance. Específicamente,
struct Foo {
int* y;
Foo() : y(new int()) { }
~Foo() { delete y; }
};
creará y
en el montón independientemente de si se creó un objeto Foo
en la pila o en el montón.
Te refieres
Foo* bar = new Foo();
supongo. Eso se crea en el montón.