Перегрузка оператора delete в базовом классе - PullRequest
6 голосов
/ 15 июня 2011

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

Если выражение delete начинается с унарного оператора ::, имя функции освобождения ищется в глобальной области видимости. В противном случае, если выражение 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 :: delete () из-за виртуального деструктора.]

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

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

§5.3.5.5 также может иметь отношение:

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

Ответы [ 2 ]

6 голосов
/ 15 июня 2011

Я не знаю много о 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

Интересно: D0 # deleting destructor, что означает, что хотя delete не является виртуальным, поскольку он вызывается из виртуального деструктора, его можно считать виртуальным для всех эффектов и целей.

0 голосов
/ 17 июня 2013

После копания в ассемблерный код в emit по GCC 4.8

GCC сгенерирует два куска кода (для класса, деструктор которого является виртуальным):

One is assembly snippet#1 for {Destructor + Dealloc}
The other is assembly snippet#2 for {Destructor only}

И для классачей деструктор не является виртуальным, инструкция функции освобождения вызова сгенерирует в точке, где вы вызываете delete.

(В следующем обсуждении предполагается, что деструктор является виртуальным)И если ваш код выглядит следующим образом:

p->C::~C()  // this will be translate to call snippet#2

Таким образом, функция освобождения связывается вместе с виртуальным деструктором.Поэтому я думаю, что это ответит на ваш вопрос о том, как функция deallocate реализована как виртуальная, так и статическая.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...