¿Este tipo de memoria se asigna en el montón o la stack?

En el contexto de C ++ (no es que importe):

class Foo{ private: int x[100]; public: Foo(); } 

Lo que he aprendido me dice que si creas una instancia de Foo así:

 Foo bar = new Foo(); 

Entonces la matriz x se asigna en el montón, pero si creaste una instancia de Foo así:

 Foo bar; 

Luego se crea en la stack.

No puedo encontrar recursos en línea para confirmar esto.

Dada una pequeña modificación de tu ejemplo:

 class Foo{ private: int x[100]; int *y; public: Foo() { y = new int[100]; } ~Foo() { delete[] y; } } 

Ejemplo 1:

 Foo *bar = new Foo(); 
  • xey están en el montón:
  • sizeof (Foo *) se crea en la stack.
  • sizeof (int) * 100 * 2 + sizeof (int *) está en el montón

Ejemplo 2:

 Foo bar; 
  • x está en la stack, y y está en el montón
  • sizeof (int) * 100 está en la stack (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 comstackdor y plataforma.

Estrictamente hablando, de acuerdo con el estándar, el objeto no necesita existir en una stack 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:

  1. duración de almacenamiento estático
  2. duración de almacenamiento automático
  3. duración de almacenamiento dynamic

La duración del almacenamiento automático se implementa (casi siempre) con la stack.

La duración del almacenamiento dynamic se implementa típicamente utilizando el montón (en última instancia a través de malloc() ), aunque esto puede ser anulado incluso por el usuario del comstackdor.

La duración del almacenamiento estático es lo que típicamente se conoce como globales (o almacenamiento estático).

El estándar tiene esto que decir acerca de estas cosas (los siguientes son extractos de varios bits de 3.7 – Duración de almacenamiento):

Las duraciones de almacenamiento estáticas y automáticas están asociadas a los objetos introducidos por las declaraciones (3.1) y creados implícitamente por la implementación (12.2). La duración de almacenamiento dynamic se asocia con objetos creados con operador nuevo (5.3.4).

Todos los objetos que no tienen una duración de almacenamiento dinámica ni son locales tienen una duración de almacenamiento estática. El almacenamiento para estos objetos durará por la duración del progtwig (3.6.2, 3.6.3).

Los objetos locales explícitamente declarados automáticos o registrados o no declarados explícitamente estáticos o externos tienen una duración de almacenamiento automática. El almacenamiento de estos objetos dura hasta que el bloque en el que se crearon sale.

Los objetos se pueden crear dinámicamente durante la ejecución del progtwig (1.9), usando expresiones nuevas (5.3.4), y destruidos usando delete-expressions (5.3.5). La implementación de AC + + proporciona acceso y administración de almacenamiento dynamic a través del operador de funciones de asignación global nuevo y operador nuevo [] y el operador de funciones de desasignación global elimina y elimina operador [].

La biblioteca proporciona definiciones predeterminadas para las funciones globales de asignación y desasignación. Algunas funciones globales de asignación y desasignación son reemplazables (18.4.1)

Y finalmente (con respecto a la matriz en su clase de ejemplo):

3.7.4 Duración de los subelementos [basic.stc.inherit]

La duración de almacenamiento de los subobjetos de miembro, los subobjetos de clase base y los elementos de matriz es la de su objeto completo (1.8).

Un objeto de tipo Foo toma el tamaño de 100 ints almacenados en secuencia. Si lo creas en la stack, lo obtendrás todo en la stack. 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 sizeof(Foo) (más posiblemente algún sobrecarga de memoria, pero ignorémoslo por el momento), que en su código de muestra implica el tamaño de 100 int s. Esto tiene que 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 un new en el constructor de Foo , esa matriz interna se creará en la stack. Nuevamente, este debe ser el caso para que la matriz se limpie automáticamente sin ningún tipo de delete cuando finaliza el scope. 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 stack o en el montón.

Te refieres

 Foo* bar = new Foo(); 

Supongo. Eso se crea en el montón.