为什么虚拟析构函数需要删除操作符 [英] Why is delete operator required for virtual destructors

查看:198
本文介绍了为什么虚拟析构函数需要删除操作符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在独立的上下文中(没有标准库,例如在操作系统开发中)使用g ++会出现以下现象:

  Base {
public:
virtual〜Base(){}
};

class Derived:public Base {
public:
〜Derived(){}
};

int main(){
Derived d;
}

链接时,它表示如下: undefined reference到操作符delete(void *)



这显然意味着g ++正在生成对delete操作符的调用,即使动态内存分配为零。这不会发生,如果析构函数不是虚拟的。



我怀疑这与类的生成的vtable有关,但我不完全确定。 为什么会发生这种情况?



如果由于缺少动态内存分配例程,我不能声明一个删除操作符,一个工作?



要成功重现g ++中的问题5.1我使用:



g ++ -ffreestanding -nostdlib foo.cpp

解决方案

因为删除了析构函数。这是当你在具有虚拟析构函数的对象上调用 delete obj 时实际调用的函数。它调用完整的对象析构函数(它链接基础对象析构函数 - 你实际定义的对象),然后调用 operator delete 。这样,在使用 delete obj 的所有地方,只需要发出一个调用,并且还用于调用 operator delete 与ISO C ++所需的 operator new 返回的指针相同(虽然这可以通过 dynamic_cast )。



它是



我不认为你可以禁用这个。


In a freestanding context (no standard libraries, e.g. in operating system development) using g++ the following phenomenon occurs:

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

class Derived : public Base {
public:
    ~Derived() {}
};

int main() {
    Derived d;
}

When linking it states something like this: undefined reference to operator delete(void*)

Which clearly means that g++ is generating calls to delete operator even though there are zero dynamic memory allocations. This doesn't happen if destructor isn't virtual.

I suspect this has to do with the generated vtable for the class but I'm not entirely sure. Why does this happen?

If I must not declare a delete operator due to the lack of dynamic memory allocation routines, is there a work around?

EDIT1:

To successfully reproduce the problem in g++ 5.1 I used:

g++ -ffreestanding -nostdlib foo.cpp

解决方案

Because of deleting destructors. That are functions that are actually called when you call delete obj on an object with virtual destructors. It calls the complete object destructor (which chains base object destructors — the ones that you actually define) and then calls operator delete. This is so that in all places where delete obj is used, only one call needs to be emitted, and is also used to call operator delete with the same pointer that was returned from operator new as required by ISO C++ (although this could be done more costly via dynamic_cast as well).

It's part of the Itanium ABI that GCC uses.

I don't think you can disable this.

这篇关于为什么虚拟析构函数需要删除操作符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆