2010-08-12 21 views
6

Cuál es la forma correcta de asignar memoria a través de new en el constructor de C++. Primera forma en la lista de argumentos:¿Cuál es la forma correcta de asignar memoria en el constructor de C++?

class Boda { 
    int *memory; 
    public: 
     Boda(int length) : memory(new int [length]) {} 
     ~Boda() { delete [] memory; } 
}; 

o en el cuerpo del constructor:

class Boda { 
    int *memory; 
    public: 
     Boda(int length) { 
      memory = new int [length]; 
     } 
     ~Boda() { delete [] memory; } 
}; 

Gracias, Boda Cydo.

+6

Sé que esto es solo un código de ejemplo, pero como está escrito, la clase tiene graves problemas de administración de memoria (la copiadora predeterminada permitirá desasignar la memoria varias veces). use RAII, use punteros inteligentes o contenedores. con una RAII adecuada, puede que no necesite usar delete yourself to all –

+8

@jk: Secundado, preferiría un 'std :: vector '. – fredoverflow

Respuesta

3

Creo que la forma más sencilla de hacer esto sería usar un boost scoped array y dejar que el código de la biblioteca bien probado de otra persona lo maneje todo para usted.

Así:

class Boda { 
    boost::scoped_array<int> memory; 
    public: 
     Boda(int length) : memory(new int [length]) {} 
     ~Boda() {} 
}; 

Por otra parte, con ámbito matrices no se pueden copiar - por lo que se evita el problema de cancelación de asignación constructor de copia desagradable mencionado en otra respuesta.

+0

En realidad, debes usar 'boost :: scoped_array'. –

+0

Gracias. Acabo de ver que era una matriz alloc. Enséñame a leer la pregunta correctamente. –

+1

'delete' es un olor a código: solo debería aparecer en clases de gestión de recursos dedicadas ... y esas ya están codificadas correctamente en las bibliotecas disponibles (STL/Boost, por ejemplo). –

-1

Si desea detectar los errores de asignación de memoria (que probablemente debería), tendrá que realizar la llamada a new en el cuerpo del constructor.

+12

No es cierto, en realidad. (Y en ambos casos. Si la asignación de memoria falla, este constructor no puede hacer nada al respecto y, por lo tanto, * no * debe detectar la excepción. Y puede usar un bloque de función try para obtener todo en un bloque try-catch .) – GManNickG

1

Yo diría que ambas son equivalentes en el efecto que producen y que ambas son "la manera correcta". Prefiero las listas de inicializadores, pero me gustaría ir con la segunda variante solo para poder probar el argumento de longitud no válida antes de tratar de asignar la memoria.

+1

Son equivalentes para tipos simples, pero en general no lo son. El uso de la lista de inicializadores construirá el objeto a partir de los argumentos; utilizando el cuerpo constructor construirá por defecto el objeto y luego lo reasignará. Esto podría ser menos eficiente y solo funcionará si el objeto es predecible y se puede asignar. –

2

Debe usar clases de administración de recursos que lo manejarán por usted. De lo contrario, se encontrará con serios problemas con la seguridad de las excepciones, además de duplicar innecesariamente la lógica existente y el mantenimiento de los operadores de copia/asignación.

0

memory variable miembro es un puntero, si asigna en lista de inicialización y falla, la clase no se ha inicializado y no es necesario para liberar más tarde (gracias a patrón de diseño RAII que es utilizado por C++ para la inicialización de clase). Si asigna su memoria dentro del cuerpo del constructor, se producirá un comportamiento similar.

Pero si quiere manejar algo, asigne su memoria en el cuerpo del constructor. Verifique algo o intente/capture o imprima algunos mensajes útiles, pero al menos, debe lanzar otra excepción, porque la inicialización de su clase está rota.

Creo que la asignación memory en el cuerpo del constructor es más legible que la otra.

Cuestiones relacionadas