【问题标题】:What's this extra parameter passed into virtual destructor?传递给虚拟析构函数的这个额外参数是什么?
【发布时间】:2011-12-24 12:39:12
【问题描述】:

我有这个代码:

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

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

我用 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]

这是实际的析构函数:

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

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

【问题讨论】:

  • 我建议你把它标记为c++-cli
  • @Gorpik 但它不是 c++-cli,我不认为
  • 对,但这是Debug项目配置还是Release?
  • @ThomasMcLeod 您被明确允许调用delete null;,并且new 有可能返回空值,因此可能不允许对其进行优化。
  • @Rup: 没错,除了 new 永远不会返回 null,但 Visual C++ 仍然会检查。

标签: c++ visual-c++ virtual-destructor


【解决方案1】:

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

【讨论】:

  • GCC 为每个类发出 3 个析构函数:常规析构函数、释放析构函数和子类析构函数。看起来 VS 只是发出一个并用 bool 调用它。
  • @deft_code:感谢您的评论:解释了我一直想知道的事情!
【解决方案2】:

析构函数使用该参数来知道它是否应该在最后调用 delete。

不想调用它的三种情况:

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

编辑:添加第三种情况

【讨论】:

    【解决方案3】:

    基本上,虚析构函数也实现了调用操作符delete。参数在那里决定是否调用它。

    见this answer that shows the meaning of such hidden destructor parameter。

    【讨论】:

    • 这个隐藏参数是 VC++ 特有的吗?我以为 gcc 选择了生成多个析构函数的道路(如果我没记错的话是 3 个)。
    • @MatthieuM.:这应该是 ABI 的一部分,所以 gcc 应该在 Windows 上做同样的事情(如果它想要兼容的话)。不过我还没试过。
    • @jpacelek:对,它在 ABI 中。实际上,gcc 在 Windows 上也可以在没有这个的情况下工作......只要你不尝试混合 gcc 和 VC++ 库:)
    • @MatthieuM.:嗯,我以为他们试图实现二进制兼容(如 icc),但似乎没有。
    • 好吧,据我所知,它们在 C 级别是兼容的 :)
    猜你喜欢
    • 1970-01-01
    • 2015-11-12
    • 2022-12-05
    • 2011-04-03
    • 2021-02-27
    • 1970-01-01
    • 2016-06-08
    • 2018-08-29
    相关资源
    最近更新 更多