什么是这个额外的参数传递到虚拟析构函数?

sha*_*oth 14 c++ visual-c++ virtual-destructor

我有这个代码:

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

int main()
{
    Class* object = new Class();
    delete object;
}
Run Code Online (Sandbox Code Playgroud)

我使用Visual C++ 10编译并获取delete object语句的反汇编:

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

这对于实际的析构函数:

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
Run Code Online (Sandbox Code Playgroud)

那是push 1在调用站点做什么,为什么test在析构函数入口点检查该值并有条件地绕过调用operator delete()

cra*_*jul 14

析构函数使用该参数来知道它是否应该在结尾调用delete.

3个你不想打电话的情况:

  • 析构函数由派生类析构函数调用
  • 对象在堆栈上分配,因此不会使用new创建.
  • 该对象是另一个对象的字段,因此不是由new创建的

编辑:添加第三个案例


Mar*_*k B 5

我相信额外的参数告诉编译器哪个析构函数是派生最多的,所以它只在适当的继承级别释放一次内存.如果我没记错的话,我在gcc中看到了类似的东西.

  • GCC为每个类发出3个析构函数:常规析构函数,解析析构函数和子类析构函数.看起来VS只是发出一个并用bool调用它. (3认同)

jpa*_*cek 5

基本上,虚拟析构函数还实现了调用操作符delete.该参数用于决定是否调用它.

请参阅此答案,其中显示了此类隐藏析构函数参数的含义.