2010-08-19 6 views
5

Recientemente leí mucho sobre "prevenir la asignación de montón para una clase" (ver this question).¿por qué prohibiría la asignación en el montón?

que era capaz de entender "cómo", pero ahora no puedo averiguar "por qué" a alguien le gustaría hacer eso.

Supongo que debe haber razones legítimas para esto, pero no puedo entenderlas.

En resumen: "¿Por qué puedo querer prohibir a los usuarios crear objetos de mi clase en el montón?"

+3

Realmente no puedo pensar en una buena razón para la pregunta que señala. Con la redacción actual de esta pregunta, es muy probable que obtenga muchas respuestas a * ¿por qué preferiría asignar en la pila en lugar del montón? *, Que es diferente de * por qué puedo querer prohibir a los usuarios crear objetos de mi clase en el montón? * –

+0

@David: modificó la redacción de acuerdo con sus consejos. Gracias. – ereOn

+0

Modifiqué el título para reflejar la pregunta real. – Puppy

Respuesta

13

Algunas clases tienen sentido solo si los objetos se instancian en la pila. Por ejemplo, Boost scoped_ptr, o lock_guard.

+1

Casi todo esto, algunas clases solo tienen sentido cuando se asignan en la pila. – Puppy

+1

En cuanto a la documentación de impulso, no parece que hayan redefinido los varios operadores 'nuevos' para evitar la asignación de montón. Está escondido o no lo hicieron. Si es así, ¿por qué? – ereOn

+1

boost :: scoped_ptr también tiene sentido para un pimpl, como se indica en el enlace. Eso no es (necesariamente) en la pila. – MSalters

5

Principalmente porque los objetos asignados a la pila se limpian automáticamente cuando salen del ámbito de aplicación, eliminando así una gran clase de errores, a saber, los errores de asignación de memoria.

+0

¿No es algo que se puede resolver más fácilmente usando punteros inteligentes? – ereOn

+0

Absolutamente. Tenga en cuenta que no dije que era aconsejable imponer la asignación de la pila;) – PaulJWilliams

+0

@Visage: gracias, notado;) – ereOn

2

Por lo general, es una buena idea evitar el uso inesperado de la clase. Por ejemplo, considere las clases Guard, que se basan en la técnica RAII. Deben asignarse en la pila y hacen su trabajo cuando están fuera del alcance. Nadie espera que los usuarios asignen objetos de protección en el montón, por lo que está explícitamente prohibido.

Mejor explícito que implícito. Herb Shutter dice que debe ser difícil usar tu clase de forma incorrecta (asignando en el montón) y muy fácil de usar correctamente (en la pila).

+0

Tienes razón en RAII, pero uno podría heap-asignar una instancia de guardia de seguridad y átelo para decir 'auto_ptr' para lograr el mismo resultado. – sharptooth

+2

Pero auto_ptr debe asignarse definitivamente en la pila. Entonces, básicamente es lo mismo, entonces ¿por qué necesitamos un nivel extra de abstracción? – SadSido

+1

@SadSido: la auto_ptr puede ser embebido en un objeto, o devuelto desde la función de, para extender el tiempo de vida del objeto que controla más allá del ámbito actual. Puedo imaginar escenarios en los que te gustaría hacer eso, y se vería frustrado si hubiera una prohibición arbitraria de la asignación del montón. –

1

La asignación de la pila es más rápida (no se necesita espacio para buscar).

+4

Sí, pero esta no es la razón por la que se prohíbe asignar objetos de una clase específica en la pila. – sharptooth

0

Para ciertas clases de objetos muy pequeños - considere puntos 3D en un motor de geometría - asignarlos individualmente en el montón es una receta para crear punteros colgantes e introducir una gran cantidad de sobrecarga - sin embargo, son vitalmente necesarios en muchos de cálculos

Por lo tanto, un mecanismo común es usar un patrón flyweight en objetos que realmente contienen una colección de puntos 3D, como la descripción de alguna entidad geométrica, y permitir su uso en el montón como resultados intermedios de los cálculos.

Ahora bien, dicho esto, se debe tener especial cuidado para evitar la copia innecesaria de datos entre la implementación flyweight, p. ListOf3DPoints y el montón asignado puntos 3D que se utilizan para resultados intermedios.

En general, he encontrado varios casos en los que he acoplado un patrón flyweight con capacidades de asignación de montones para lograr resultados óptimos - el flyweight proporciona almacenamiento persistente, las asignaciones de montón me permiten realizar manipulaciones a nivel de elemento sin tener que generar hasta otro peso mosca

4

Voy a ir contra la corriente que parece (así que espero votos hacia abajo, pero por favor deje un comentario para indicar el por qué).

No veo ninguna razón para prohibir la asignación del montón, principalmente porque no me gusta adivinar los posibles usos de las clases que creo.

Como regla de diseño, tiendo a poner tan pocas restricciones sobre los usos de mis clases como sea posible. Esto significa la menor cantidad posible de suposiciones. No hay nada más enloquecedor que no poder hacer lo que deseas simplemente porque estaba prohibido ... por razones desconocidas o simplemente incorrectas (denotando las creencias supersticiosas/erróneas del escritor de la biblioteca).

Además, el pragmatismo enseña que es casi imposible prevenir cualquier cosa en C++. Por ejemplo, algunas personas han hablado sobre guardias -> ¿y si me gustaría crear una súper clase (que convenientemente agrega el registro)? Luego pondría la clase de protección como un atributo, e incluso si su operador (la clase original) new es privado, mi superclase se puede instanciar en el montón a menos que de alguna manera se replique el mecanismo.

Entonces, en cuanto a mí, no es una cuestión de por qué o cómo. Simplemente no jugueteo con los esquemas de asignación de memoria en el código de la biblioteca, depende del usuario usar lo que sea más conveniente para ella.

+0

En realidad, tiendo a estar de acuerdo. – ereOn

Cuestiones relacionadas