2010-03-23 8 views
12

¿Destruye el destructor la memoria asignada al objeto al que pertenece o simplemente se llama para que pueda realizar algunas tareas administrativas de último minuto antes de que el objeto sea desasignado por el compilador?Destructores en C++

+2

Un destructor debe eliminar los objetos asignados dinámicamente retenidos por el objeto del destructor, pero el destructor no es responsable de liberar la memoria en la que reside su objeto. –

Respuesta

32

El 'compilador' no elimina nada. Crea código que hace cosas en tiempo de ejecución.

Cuando se escribe delete somePointer; el compilador, en esencia, escribe:

if (has_virtual_destructor(* somePointer )) { 
     // virtual dispatch to a compiler-generated function 
     dynamic_cast< true_dynamic_type * >(somePointer)->destroy_dynamic_type(); 
     /* contents of true_dynamic_type::destroy_dynamic_type() { 
       this->~true_dynamic_type(); 
       operator delete(this); // executed within class context 
     } */ 
    } else { 
     somePointer->~ClassName(); 
     operator delete(somePointer); 
    } 

En otras palabras, el destructor se llama, y ​​luego borrar el operador obtiene la llamada para liberar el almacenamiento.

Si el destructor es virtual, se utiliza un despacho virtual para realizar toda la operación en el objeto en su forma más derivada. Una forma común de implementar esto es agregar argumentos ocultos a cada destructor virtual.

Tenga en cuenta que la sentencia if de nivel superior no es realmente parte del código generado; el compilador toma esa decisión en tiempo de compilación.

+1

Eso es un montón de votos ascendentes; v) ... tal vez mencionar el elenco como verdadero dinámico escriba en el caso de un destructor virtual. (Y, la forma en que funciona la búsqueda de 'operador delete',' delete' se llama de hecho dentro de un destructor virtual "a cargo." No mencionar esto podría ser confuso para ver un rastreo de perfil.) – Potatoswatter

+0

@potatoswatter: feel feee to edit . No puedo explicar el deslizamiento de tierra, simplemente escribí lo obvio. – bmargulies

+0

Un nitpick menor: este 'if (has_virtual_destructor ...' is * not * ejecutado en tiempo de ejecución. El * compilador * puede decidir para cada tipo (dependiendo solo del tipo * static *) si tiene un destructor virtual o no virtual y emitir el código apropiado para ambas situaciones. No estoy seguro de lo que sucede cuando intentas 'borrar' un' void * 'pero mi suposición es que esto será UB. –

2

Se llama al destructor para permitir que el objeto realice la limpieza y para destruir cualquier otro objeto que el objeto haya creado.

El sistema operativo se ocupará de la desasignación del objeto después de terminar el destructor.

0

1) destructor no pertenece al objeto, que pertenece a la clase

2) Se llama destructor para todos los tipos definidos por el usuario (objetos) de clase dentro de su clase.

3) La limpieza es la actividad opcional que se realiza sólo si es realmente necesario

0

La memoria se desasigna después se cierra la función destructor y antes de la ejecución vuelve al "eliminar" llamar o punto donde va una instancia de objeto fuera del ámbito. En teoría, es posible configurar un administrador de memoria diferente para manejar nuevo y eliminar, pero eso sería un cambio explícito del comportamiento predeterminado.

0

Más específicamente, nadie más que el programador desasigna memoria en C++. Si el objeto está en la pila, reside en el espacio de la memoria del programa y ocupa espacio durante la vida útil del programa. Si está en el montón, quien creó el objeto es responsable de desasignarlo. Eso es lo que deletehace. Esto nos lleva al destructor: si crea objetos en su clase, el destructor le permite eliminarlos a medida que la clase abandona el alcance. Te permite "apagar las luces mientras te vas".

+0

No hay "el programador". Si yo, un programador, escribo una clase con una variable miembro de tipo std :: vector , No necesito, y no debo escribir co de para eliminarlo. El compilador generará automáticamente código para llamar al destructor std :: vector que algún otro programador escribió en algún momento, y estará disponible en el archivo de encabezado . –

+0

Siempre hay un "programador" incluso si no es específicamente usted: las computadoras no matan personas, las personas matan personas. O pierde memoria, lo que sea. Si crea una variable miembro de std :: vector, eso está en la pila. Sin asignación, sin responsabilidad. Si su std :: vector asigna memoria de pila internamente, entonces "el programador" en ese caso es el programador de std :: vector, no usted, por lo que no debería tener que preocuparse por ello. – Matt

0

Destructores llaman automáticamente a los destructores en las variables miembro del objeto que se destruye. Esos destructores pueden o no liberar memoria. Sin embargo, un puntero no tiene destructor, o si lo prefiere, el destructor de un puntero no hace nada. No libera la memoria a la que apunta. Si un objeto contiene un puntero a un objeto obtenido de "nuevo" o "malloc", le corresponde al programador de ese objeto hacer que el destructor haga lo correcto. Debería programar su destructor para "borrar" o "liberar" la memoria si es conceptualmente parte del objeto que se está destruyendo. Por ejemplo, un objeto "vector" típicamente obtiene memoria del montón, porque la cantidad de memoria requerida generalmente no se conoce en tiempo de compilación. Esa memoria es conceptualmente parte del objeto vector, y así el programador de la clase vector debe llamar "eliminar" en el destructor. Las clases de Biblioteca de plantillas estándar como std :: vector lo hacen correctamente.

Por otro lado, algunos objetos contienen referencias a otros objetos. Un diccionario o índice contendrá referencias (punteros) a objetos que no son conceptualmente parte de ellos. Esa memoria no debe ser liberada por el destructor. (Si elimina su número de teléfono de la guía telefónica, no desea que desaparezca automáticamente).

Existen excepciones que el principiante no necesita preocuparse al principio. Una es cuando el objeto y sus contenedores están programados para usar el recuento de referencias, y el objeto al que se hace referencia no se libera realmente hasta que el último objeto al que se hace referencia lo deja ir. Otra excepción es en el caso de "colocación nueva".

Cuestiones relacionadas