在使用g ++的独立上下文(没有标准库,例如在操作系统开发中)中,会出现以下现象:
class Base {
public:
virtual ~Base() {}
};
class Derived : public Base {
public:
~Derived() {}
};
int main() {
Derived d;
}
链接时,请说明以下内容:undefined reference to operator delete(void*)
这显然意味着即使动态内存分配为零,g ++也会生成删除运算符的调用。如果析构函数不是虚拟的,那么这不会发生。
我怀疑这与课堂生成的vtable有关,但我并不完全确定。 为什么会这样?
如果由于缺少动态内存分配例程而不能声明删除操作符,是否有解决方法?
EDIT1:
为了成功地重现我使用的g ++ 5.1中的问题:
g ++ -ffreestanding -nostdlib foo.cpp
答案 0 :(得分:13)
因为删除了析构函数。这是在使用虚拟析构函数的对象上调用delete obj
时实际调用的函数。它调用完整的对象析构函数(它链接基础对象析构函数 - 您实际定义的那些),然后调用operator delete
。这样,在使用delete obj
的所有地方,只需要发出一个调用,并且还用于使用operator delete
根据需要返回的相同指针调用operator new
通过ISO C ++(虽然这可以通过dynamic_cast
来实现更高成本。)
它是GCC使用的Itanium ABI的一部分。
我认为你不能禁用它。
答案 1 :(得分:0)
在C ++ 20中,现在有一个修复程序:P0722R3。 static void operator delete(T*, std::destroying_delete_t)
释放功能。它本质上映射到销毁的析构函数。
您可以使其不调用::operator delete
,例如:
class Base {
public:
void operator delete(Base* p, std::destroying_delete_t) {
// Shouldn't ever call this function
std::terminate(); // Or whatever abort-like function you have on your platform
// The default implemenation without any overrides basically looks like:
// p->~Base(); ::operator delete(p);
// Which is why the call to `operator delete` is generated
}
virtual ~Base() {}
};
class Derived : public Base {
public:
// Calls Base::operator delete in deleting destructor, so no changes needed
~Derived() {}
};
int main() {
Derived d;
}
删除析构函数是您执行delete ptr_to_obj;
时所调用的析构函数。它只能由delete
表达式调用,因此,如果代码中没有表达式,则可以。如果这样做,则可以用::delete ptr_to_obj;
替换它们,删除的析构函数将不再被调用(其目的是为类调用重写的operator delete
,而::delete
仅调用全局::operator delete
)