明确调用子析构函数也会调用父析构函数

时间:2014-10-24 23:45:04

标签: c++ memory memory-management

对于我用C ++编写的内存管理器作为概念证明,为了跟踪已分配的对象,我在函数中使用malloc()分配内存,然后将指针返回到该内存并使用安置新运营商。然后,为了跟踪删除对象的时间,我将指针传递给另一个函数,以便在指针上调用free()

但是,由于我使用的是free()而不是delete,因此对象的构造函数不会像通常那样自动调用,因此我必须自己调用它。此外,由于内存管理器设计用于处理任何对象,因此可以想象(甚至可能)在其生命周期的某个时刻,它必须释放可能具有多个父类或深入继承树的对象。

我对此的初步解决方案是调用基础对象析构函数,它将调用所有子析构函数(如果相信this question),但由于这些对象实际上可以是任何东西并且具有任何集合继承,没有办法知道它的真正基类是什么。

所以我的问题是:显式调用子类析构函数也会自动调用所有的基本析构函数,就像删除一样,或者没有办法轻易做到这一点?

1 个答案:

答案 0 :(得分:3)

是的,这是有保障的。 C ++ 14 [class.dtor] / 8:

  

执行析构函数体并销毁正文中分配的任何自动对象后,类X的析构函数调用X的直接非变量非静态数据成员的析构函数, X直接基类的析构函数,如果X是派生类最多的类(12.6.2),它的析构函数调用X虚拟基的析构函数类。

具体而言,对于任何类型T,您始终可以执行此操作:

void * addr = ::operator new(sizeof T);
T * p = ::new (addr) T(/* ctor args */);
p->~T();                                    // !
::operator delete(addr);

或者,如果您不想调用分配器:

{
    std::aligned_storage_t<sizeof(T), alignof(T)> storage;
    T * p = ::new (static_cast<void *>(std::addressof(storage))) T(/* args */);
    p->~T();
}