在基类中重载operator delete

Eti*_*mps 6 c++ operator-overloading

从C++标准(ISO/IEC 14882:2003(E)),§12.5.4,关于重载operator delete:

如果delete-expression以unary :: operator开头,则在全局范围内查找释放函数的名称.否则,如果使用delete-expression释放静态类型具有虚拟析构函数的类对象,则释放函数是在动态类型的虚拟析构函数(12.4)的定义中通过查找找到的函数.否则,如果使用delete-expression释放类T或其数组的对象,则该对象的静态和动态类型应相同,并且在T的范围内查找解除分配函数的名称.如果此查找未能找到名称,在全局范围内查找名称.如果查找结果不明确或不可访问,或者查找选择了放置重新分配功能,则程序格式错误.

§12.5.7也很有趣:

由于成员分配和释放功能是静态的,因此它们不能是虚拟的.[注意:但是,当delete-expression的cast-expression引用类类型的对象时,因为实际调用的释放函数是在作为对象动态类型的类的范围内查找的,如果是析构函数是虚拟的,效果是一样的.例如,

struct B {
    virtual ˜B();
    void operator delete(void*, size_t);
};
struct D : B {
    void operator delete(void*);
};
void f()
{
    B* bp = new D;
    delete bp; // uses D::operator delete(void*)
}
Run Code Online (Sandbox Code Playgroud)

这里,由于虚拟析构函数,D ::非数组对象的存储由D :: operator delete()释放.

看完之后,我想知道......

  • 所有主要的C++编译器(MSVC++,GCC)都完全支持这部分标准吗?
  • 如果是这样,他们是怎么做到的?隐藏虚拟功能?"特殊"虚拟析构函调用?RTTI?
  • 使用标准中的示例:如果在单独的EXE/DLL/DSO中定义了f()和D :: operator delete(),是否会出现问题?(假设所有内容都是使用相同的编译器编译的,当然)

§5.3.5.5也可能是相关的:

在第一个替代(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应为操作数的动态类型的基类,静态类型应具有虚拟析构函数或行为未定义.在第二个备选(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义.

Mat*_* M. 6

我对VC++ ABI知之甚少,但Itanium ABI已有详细记载.

抬头看着名称改造方案,人们看到:

<ctor-dtor-name> ::= C1     # complete object constructor
                 ::= C2     # base object constructor
                 ::= C3     # complete object allocating constructor
                 ::= D0     # deleting destructor
                 ::= D1     # complete object destructor
                 ::= D2     # base object destructor
Run Code Online (Sandbox Code Playgroud)

有趣的是:D0 # deleting destructor这意味着即使delete它是非虚拟的,因为它是从虚拟析构函数调用的,所以它可以被视为虚拟的所有效果和目的.