Ok, así que estoy muy nuevo en la programación C++, y he estado mirando a su alrededor por un par de días para una respuesta decisiva para esto. ¿CUÁNDO debería declarar las variables miembro en el montón frente a la pila? La mayor parte de las respuestas que he encontrado han abordado otras cuestiones, pero quiero saber cuándo es mejor utilizar el montón de variables miembro y por qué es mejor para amontonar los miembros en lugar de apilarlos.para declarar variables miembro en el montón de C++
Respuesta
Hay dos conceptos importantes para captar primero:
uno debe evitar pensar en términos de "montón" y "pila". Esos son detalles de implementación de su compilador/plataforma, no del lenguaje. En su lugar, pensar en términos de vidas objeto: debería vida útil del objeto corresponda a la de su "padre", o debe sobrevivir a ella? Si necesita lo último, necesitará usar
new
(directa o indirectamente) para asignar dinámicamente un objeto.Variables miembro siempre tienen la misma vida que su elemento primario. La variable miembro puede ser un puntero y el objeto al que apunta puede tener una vida útil independiente. Pero el objeto apuntado no es una variable miembro.
Sin embargo, no hay una respuesta general a tu pregunta. Crudo hablando, no se asigna dinámicamente a menos que haya una buena razón para hacerlo. Como indiqué anteriormente, estas razones generalmente corresponden a situaciones en las que la duración de la vida debe diferir de su "padre".
1. De hecho, el estándar de C++ en realidad no hablar de "montón" y "pila". Es importante tenerlos en cuenta al optimizar o, en general, pensar en el rendimiento, pero en su mayoría son irrelevantes desde el punto de vista de la funcionalidad del programa.
"generalmente corresponden a situaciones en las que la duración de la vida debe diferir de la de su padre": ¿podemos hablar de algo como miembro entonces? –
@JamesKanze: De hecho, debería aclarar eso. –
Los objetos también requieren tiempo de vida dinámico si tienen un tamaño dinámico o para convertir un objeto en una clase base virtual. –
La pila se refiere a call stack
. Las llamadas a función, las direcciones de retorno, los parámetros y las variables locales se mantienen en la pila de llamadas. Utiliza memoria de pila cada vez que pasa un parámetro o crea una variable local. La pila solo tiene almacenamiento temporal. Una vez que la función actual está fuera del alcance, ya no tiene acceso a ninguna variable para los parámetros.
El montón es una gran cantidad de memoria utilizada para la asignación dinámica. Cuando utiliza el operador new
para asignar memoria, esta memoria se asigna desde el montón. Desea asignar memoria de montón cuando crea objetos que no desea perder después de que la función actual finaliza (pierde alcance). Los objetos se almacenan en el montón hasta que el espacio se desasigna con delete
o free()
.
Los objetos también requieren tiempo de vida dinámico si tienen un tamaño dinámico o para convertir un objeto en una clase base virtual. –
variables de ellos son miembros de la clase en sí. No son ni sobre el montón ni en la pila, o más bien, son que cada vez la clase en sí es .
Hay muy pocas razones para agregar un nivel de indirección, y asignar un miembro separado en el montón: el polimorfismo (si el tipo del miembro no es siempre la misma) es con mucho el más común.
Los objetos también requieren tiempo de vida dinámico si tienen un tamaño dinámico o para convertir un objeto en una clase base virtual. –
@MooingDuck Los objetos que tienen un tamaño dinámico deben ser gestionados por su propia clase (por ejemplo, 'std :: vector'): no los asigne _miles como miembros; haces que el contenedor sea el miembro. Y el lanzamiento a una clase base virtual o lo que sea implica que el miembro es polimórfico, que es lo que mencioné. –
Muy bien, bastante bien –
Para obtener un poco de terminología: lo que usted llama heap
y stack
describe la vida útil de los objetos.La primera significa que la vida útil es dynamic
, la segunda automatic
y la tercera (que no menciona) es static
.
Por lo general, necesitará dynamic
vida útil de un objeto cuando debería durar más que el ámbito en el que se creó. Otro caso común es cuando desea que se comparta entre diferentes objetos principales. Además, la vida dinámica también es necesaria cuando se trabaja con un diseño que está fuertemente orientado a objetos (usa mucho polimorfismo, no usa valores), p. Qt
.
Una expresión idiomática que requiere tiempos de vida dinámicos es el idioma pimpl.
La mayoría de las bibliotecas de programación genérica están más enfocadas hacia el valor y la semántica de valores, por lo que no utilizará mucho esa vinculación dinámica y las vidas automáticas se volverán mucho más comunes.
También hay algunos ejemplos donde se requiere la asignación dinámica por razones específicas más de ejecución:
- objetos dinámicamente de tamaño (recipientes) manejar tipos incompletas
- (ver pimpl-idioma)
- fácil nulabilidad de un tipo
Todas estas son solo pautas generales y deben decidirse caso por caso. En general, prefiere objetos automáticos sobre dinámicos.
Considere este ejemplo:
Implementa una lista vinculada que tiene un miembro de campo cabeza de nodo de clase.
Cada nodo tiene un miembro de campo next
. Si este miembro del tipo Nodo y no Nodo * el tamaño de cada Nodo dependerá del número de nodos después de él en la cadena.
Por ejemplo, si tiene 100 nodos en su lista, su miembro principal será enorme. Porque contiene el siguiente nodo dentro de sí mismo, por lo que necesita tener el tamaño suficiente para mantenerlo y luego el siguiente y así sucesivamente. Por lo tanto, la cabeza debe tener espacio suficiente para contener 99 nodos los siguientes 98 y así sucesivamente ...
Desea evitar eso, así que en este caso es mejor tener un puntero al siguiente nodo en cada nodo en lugar de próximo nodo en sí.
- 1. C++ Etiqueta sobre las variables de miembro en el montón
- 2. ¿Puedes declarar un puntero en el montón?
- 3. C++ apilar las variables y variables montón
- 4. ¿Las variables miembro de un objeto que está en el montón también están automáticamente en el montón?
- 5. C# para las variables miembro privadas
- 6. caracteres de subrayado posteriores para las variables miembro en C++
- 7. ¿Cómo declarar variables estáticas en Objective-C?
- 8. Atributos/variables miembro en interfaces?
- 9. ¿Alguna posibilidad de declarar indexadores en C# como miembro abstracto?
- 10. Declarar múltiples variables en Scala
- 11. Variables C++: declarar y definir. Herencia
- 12. ¿Declarar las variables de C++ ayuda o perjudica el rendimiento?
- 13. Objective-C, variables miembro y variables de clase
- 14. ¿Podemos declarar variables en el archivo app.config
- 15. MYSQL declarar variables
- 16. Error de enlace al declarar variables estáticas públicas en C++
- 17. Variables miembro de iteración
- 18. declarar múltiples variables en JavaScript
- 19. Ventana vs Var para declarar variables
- 20. SQL declarar variables
- 21. Cambio de fuente para las variables miembro en Visual Studio
- 22. ¿Cómo declarar las "variables" locales como finales en Objective-C?
- 23. Declarar e inicializar variables en bucle for
- 24. ¿Inicializar el mapa y establecer las variables miembro de la clase para vaciar en C++?
- 25. Debería declarar explícitamente mis variables en VB6
- 26. Variables miembro estáticas protegidas
- 27. C++ funciones de miembro volátil
- 28. ¿Cómo declarar variables estáticas en Delphi 2009?
- 29. ¿Cómo puedo mejorar este diseño que me obliga a declarar una función miembro const y declarar variables mutables?
- 30. ¿pueden usarse las funciones miembro para inicializar las variables miembro en una lista de inicialización?
* las variables * member * se refieren a los miembros * class * y, como tales, van a donde va la * instancia * de la clase. – CapelliC