Оператор перегрузки delete в базовом классе

Из стандарта C ++ (ISO / IEC 14882: 2003 (E)), §12.5.4, о перегрузке operator delete :

Если выражение удаления начинается с унарного оператора ::, имя функции освобождения ищется в глобальной области. В противном случае, если выражение удаления используется для освобождения объекта класса, статический тип которого имеет виртуальный деструктор, функция освобождения - это функция, найденная поиском в определении виртуального деструктора динамического типа (12.4). В противном случае, если выражение удаления используется для освобождения объекта класса T или его массива, статический и динамический типы объекта должны быть идентичными, и имя функции освобождения ищется в области T. Если этот поиск не может найти имя, имя ищется в глобальной области. Если результат поиска неоднозначен или недоступен, или если поиск выбирает функцию освобождения размещения, программа имеет неправильный формат.

§12.5.7 также интересен:

Поскольку функции выделения и освобождения членов статичны они не могут быть виртуальными. [Примечание: однако, когда выражение приведения в выражении удаления ссылается на объект типа класса, потому что фактически вызванная функция освобождения просматривается в области видимости класса, который является динамическим типом объекта, если деструктор виртуально, эффект тот же. Например,

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*)
}

Здесь память для объекта, не являющегося массивом класса D, освобождается D :: operator delete () из-за виртуального деструктора.]

Прочитав это, мне интересно ...

  • Полностью ли поддерживается эта часть стандарта всеми основными компиляторами C ++ (MSVC ++, GCC)?
  • Если да, то как они это сделали? Скрытая виртуальная функция? Вызов "специального" виртуального деструктора? RTTI?
  • Используя пример из стандарта: могут ли возникнуть проблемы, если f () и D :: operator delete () определены в отдельных EXE / DLL / DSO? (Предполагая, что все скомпилировано с использованием одного и того же компилятора, конечно)

§5.3.5.5 также может быть актуальным:

В первой альтернативе (удалить объект), если статический тип операнда отличается от его динамического type, статический тип должен быть базовым классом динамического типа операнда, а статический тип должен иметь виртуальный деструктор, иначе поведение не определено. Во втором варианте (удалить массив), если динамический тип удаляемого объекта отличается от его статического типа, поведение не определено.

6
задан casperOne 10 May 2012 в 12:49
поделиться