为什么虚拟析构函数需要删除操作符 [英] Why is delete operator required for virtual destructors
问题描述
在独立的上下文中(没有标准库,例如在操作系统开发中)使用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屋!