对于我用C ++编写的内存管理器作为概念证明,为了跟踪已分配的对象,我在函数中使用malloc()
分配内存,然后将指针返回到该内存并使用安置新运营商。然后,为了跟踪删除对象的时间,我将指针传递给另一个函数,以便在指针上调用free()
。
但是,由于我使用的是free()
而不是delete
,因此对象的构造函数不会像通常那样自动调用,因此我必须自己调用它。此外,由于内存管理器设计用于处理任何对象,因此可以想象(甚至可能)在其生命周期的某个时刻,它必须释放可能具有多个父类或深入继承树的对象。
我对此的初步解决方案是调用基础对象析构函数,它将调用所有子析构函数(如果相信this question),但由于这些对象实际上可以是任何东西并且具有任何集合继承,没有办法知道它的真正基类是什么。
所以我的问题是:显式调用子类析构函数也会自动调用所有的基本析构函数,就像删除一样,或者没有办法轻易做到这一点?
答案 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();
}