¿Qué es este parámetro adicional pasado al destructor virtual?

Tengo este codigo:

class Class {
public:
    virtual ~Class() {}
};

int main()
{
    Class* object = new Class();
    delete object;
}

que compilo con Visual C ++ 10 y obtengo este desmontaje para delete object declaración:

delete object;
test        eax,eax  
je          wmain+23h (401041h)  
mov         edx,dword ptr [eax]  
push        1  
mov         ecx,eax  
call        dword ptr [edx]

y esto para el destructor real:

Class::`scalar deleting destructor':
test        byte ptr [esp+4],1  
push        esi  
mov         esi,ecx  
mov         dword ptr [esi],offset Class::`vftable' (402100h)  
je          Class::`scalar deleting destructor'+18h (401018h)  
push        esi  
call        dword ptr [__imp_operator delete (4020A8h)]  
pop         ecx  
mov         eax,esi  
pop         esi  
ret         4

Que es eso push 1 haciendo en el sitio de la llamada y por qué test en el punto de entrada del destructor, verificando ese valor y omitiendo condicionalmente la llamada a operator delete()?

preguntado el 08 de noviembre de 11 a las 14:11

Te sugiero que etiquetes esto como c++-cli -

@Gorpik pero no es c ++ - cli, no creo -

Correcto, pero ¿se trata de una configuración o versión de un proyecto de depuración? -

@ThomasMcLeod Tienes permiso explícito para llamar delete null;, y existe la posibilidad de que new devolvió un valor nulo, por lo que probablemente no esté permitido optimizarlo. -

@Rup: Exactamente, excepto new nunca regresa null, sin embargo, Visual C ++ todavía lo comprueba. -

3 Respuestas

El destructor usa el argumento para saber si debe llamar a delete al final.

3 casos en los que no quieres llamarlo:

  • El destructor es llamado por un destructor de clase derivada
  • El objeto se asigna en la pila, por lo que no se crea con nuevo.
  • El objeto es un campo de otro objeto, por lo tanto, no creado por nuevos

EDITAR: agregar un tercer caso

respondido 08 nov., 11:23

Básicamente, el destructor virtual también implementa la eliminación del operador de llamada. El parámetro está ahí para decidir si lo llama o no.

Consulte nuestra página esta respuesta que muestra el significado de dicho parámetro destructor oculto.

contestado el 23 de mayo de 17 a las 15:05

¿Este parámetro oculto es específico de VC ++? Pensé que gcc había elegido el camino de generar múltiples destructores en su lugar (3 si no recuerdo mal). - Matthieu M.

@MatthieuM .: Esto debería ser parte de la ABI, por lo que gcc debería hacer lo mismo en Windows (si quiere ser compatible). Sin embargo, no lo he probado. - jpalecek

@jpacelek: ah, está en el ABI. En realidad, gcc también funciona sin esto en Windows ... siempre que no intente mezclar las bibliotecas gcc y VC ++ :) - Matthieu M.

@MatthieuM .: Hmm, pensé que intentaban ser compatibles con binarios (como icc), pero parece que no es así. - jpalecek

bueno, son compatibles en el nivel C hasta donde yo sé :) - Matthieu M.

Creo que el parámetro adicional le dice al compilador qué destructor es el más derivado, de modo que solo desasigna la memoria una vez, en el nivel apropiado de herencia. He visto algo similar en gcc si mal no recuerdo.

respondido 08 nov., 11:18

GCC emite 3 destructores, para cada clase: un destructor normal, un destructor de desasignación y un destructor de subclase. Parece que VS solo emite uno y lo llama con un bool. - deft_code

@deft_code: Gracias por ese comentario: ¡Explica algo sobre lo que me he estado preguntando por un tiempo! - Ben Jackson

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.