出于我不希望在这里深入讨论的原因,我需要在庞大的现有代码库中充分利用自动operator new
和operator delete
来规范分配和释放。为此,我将使用new X(...)
重写(使用clang前端遍历)每次出现new (allocate<X>()) X(...)
,其中allocate<X>
的默认实现会调用特定于类的{{1} }(如果存在),否则为operator new
。我知道这不是100%的声音,但对于我要定位的代码库来说,它“足够好”。
现在,我正在尝试为::operator new
引入类似的拦截行为,但是由于虚拟delete
的怪异特性,这比预期的要难。来自https://en.cppreference.com/w/cpp/memory/new/operator_delete:
在多态类上对特定于类的
operator delete
的调用是唯一通过动态分派调用静态成员函数的情况。
考虑以下示例:
T::operator delete
理想情况下,我想将代码库中每次出现的struct A {
virtual ~A() { cout << "~A" << endl; }
static void operator delete(void* ptr) {
cout << "A::operator delete" << endl;
::operator delete(ptr);
}
};
struct B : public A {
virtual ~B() { cout << "~B" << endl; }
static void operator delete(void* ptr) {
cout << "B::operator delete" << endl;
::operator delete(ptr);
}
};
替换为delete x
,默认情况下它等效于deleteWrapper(x)
,但是我可以添加额外的工具并专门化必要时,将其用于某些类型的delete x
。
我以为可以做到这一点:
x
但是(除了调用未定义的行为之外),这不等于template <typename T>
void deleteWrapper(T* x) {
x->~T();
// The deallocation behavior here should "tweakable" for certain types
// of T, for example I might need different implementations for
// std::pair<int, int> and std::pair<std::string, int>
x->operator delete(x);
}
:在上述类型层次结构中,delete x
调用deleteWrapper(static_cast<A*>(new B))
而不是A::operator delete
。在不使用B::operator delete
的情况下,是否可以通过给定多态指针来调用正确的重载?
如果存在涉及一定数量的源代码重写的解决方案,由于我已经在使用经过修改的clang,因此我也很想听听它。