2010-05-26 10 views
8

Estoy estudiando para un examen final y me encontré con una pregunta curiosa que era parte del examen que nuestro maestro le dio el año pasado a algunas almas pobres. La pregunta es más o menos así:¿Qué sucede con los miembros de la clase cuando se usa malloc en lugar de nuevo?

¿El siguiente programa es correcto o no? Si es así, anote qué produce el programa. Si no es así, anote por qué.

El programa:

#include<iostream.h> 
class cls 
{  int x; 
     public: cls() { x=23; } 
     int get_x(){ return x; } }; 
int main() 
{  cls *p1, *p2; 
     p1=new cls; 
     p2=(cls*)malloc(sizeof(cls)); 
     int x=p1->get_x()+p2->get_x(); 
     cout<<x; 
     return 0; 
} 

Mi primer instinto fue responder con "el programa no es correcto, ya que new deben utilizarse en lugar de malloc". Sin embargo, después de compilar el programa y verlo como salida 23, me di cuenta de que esa respuesta podría no ser correcta.

El problema es que esperaba p2->get_x() para devolver algún número arbitrario (lo que sucedió que estaba en ese punto de la memoria cuando se llamó malloc). Sin embargo, devolvió 0. No estoy seguro de si esto es una coincidencia o si los miembros de la clase se inicializaron con 0 cuando es malloc -ed.

  • ¿Es este comportamiento (p2->x siendo 0 después de malloc) el valor por defecto? ¿Debo tener esperado esto?
  • ¿Cuál sería su respuesta a la pregunta de mi profesor? (Además de olvidarse de #include <stdlib.h> para malloc: P)
+4

¿Por qué el 0 tampoco puede ser un número arbitrario? –

+0

Aparte de todo lo demás '' debería simplemente ser ''. –

+0

También podría corregir fugas de memoria de su maestro. –

Respuesta

14
  • ¿Este comportamiento (p2-> x es 0 después de malloc) es el predeterminado? ¿Debería haber esperado esto?

No, p2-> x puede ser cualquier cosa después de la llamada a malloc. Simplemente resulta ser 0 en su entorno de prueba.

  • ¿Cuál sería su respuesta a la pregunta de mi profesor? (además de olvidar #include para malloc: P)

Lo que todo el mundo le ha dicho, nuevo combina la llamada para obtener memoria del freestore con una llamada al constructor del objeto. Malloc solo hace la mitad de eso.

Reparándolo: Mientras el programa de muestra está equivocado. No siempre es incorrecto usar "malloc" con las clases. Es perfectamente válido en una situación de memoria compartida sólo hay que añadir una llamada en lugar de nuevo:

p2=(cls*)malloc(sizeof(cls)); 
new(p2) cls; 
+2

Si está utilizando la ubicación nueva, también debe llamar explícitamente al destructor (no puede usar la eliminación ya que no utilizó la función nueva). También debe enfatizar que esto no es común (se usa principalmente al construir sus propios contenedores cuando se preasigna el almacenamiento para varios elementos (no solo uno)) –

+1

Yo discutiría el uso de 'reinterpret_cast'. Enfatiza que estás haciendo algo muy peligroso. –

+0

En respuesta a Matthieu M., no me gusta editar preguntas de 5 años, pero IMrecentE, reescribiría mi último ejemplo anterior como void * p2Buffer = malloc (sizeof (cls)); cls * p2 = new (p2Buffer) cls ;. De esta forma, luego puede llamar a p2-> ~ cls y liberar (p2Buffer); y es obvio que p2 es el "objeto de clase" y p2Buffer es el puntero de memoria asignado. – jmucchiello

3

nuevas llamadas del constructor, malloc no lo hará. Entonces su objeto estará en un estado desconocido.

+0

Sé que 'malloc' no llama al constructor. Mi pregunta era sobre el miembro de la clase 'x' - ¿se inicializa con 0 o tiene algún valor aleatorio que estaba en la memoria en ese punto? – Felix

+1

@Felix: si no se llama al constructor, el valor de los datos del miembro es un comportamiento indefinido. – Cascabel

+1

@Felix Inicializar x ocurre en el constructor, por lo que no está definido. Incluso el uso de 'new' no daría como resultado cero a menos que x realmente se establezca en 0 en el constructor; los campos de miembro no obtienen inicializaciones predeterminadas como en Java –

1

El comportamiento real es desconocido, porque new actúa de forma similar a malloc + constructor llamada.

En su código, falta la segunda parte, por lo tanto, podría funcionar en un caso, no podría, pero no puede decir exactamente.

0

Por qué no puede ser 0 un número arbitrario también?¿Estás ejecutando en modo Depuración? ¿Qué compilador?

VC++ rellena previamente la memoria asignada con una cadena de valores 0xCC de bytes (en modo de depuración de curso) por lo que no habría obtenido un cero para una respuesta si la estuviera usando.

+0

Estoy usando g ++, sin depuración. – Felix

0

Malloc no garantiza que ponga a cero la memoria asignada y el resultado del programa no está definido.

De lo contrario, hay muchas otras cosas que impiden que este programa sea correcto C++. cout está en el espacio de nombres std, malloc tiene que estar incluido a través de #include <cstdlib> y iostream.h no cumple con los estándares tampoco.

Cuestiones relacionadas