Почему оператор delete требуется быть статичным?

Я нашел этот вопрос, спросив то же самое, однако только 'новой' части ответили, таким образом, здесь идет снова.

Почему оператор delete требуется быть статичным? Так или иначе это не имеет смысла. Новый оператор имеет смысл, точно так же, как конструктор не может быть виртуальным, ни один не может новый оператор. Однако деструктор может (и если) быть виртуальным при использовании наследования для разрешения разрушения используемых объектов (посредством полиморфизма) как базовый класс.

Я понимаю, что, когда оператор delete называют, объект был уже уничтожен, таким образом, не 'это' существует. Все же это все еще имеет смысл, с помощью того же обоснования, как с виртуальным деструктором, чтобы иметь оператор delete соответствуют новому оператору, который создал объект.

Это - то, что я имею в виду

class A
{
  public:
    virtual ~A() {}
};

class B : public A
{
  public:
    void* operator new (size_t sz);
    void  operator delete (void* ptr, size_t sz);
};

теперь, если мы делаем

A *ptr = new B();
delete ptr; // <-- fail

Оператор delete A (значение по умолчанию) нужно было назвать, так как это статично, и это не знало (ни для чего кроме тривиального случая здесь) во время компиляции, какой оператор delete является корректным.

Однако я сделал маленькую тестовую программу с кодом выше (просто malloc/free в новых / операторах delete, и оператор печати в удаляет), и скомпилировал его с помощью g ++. Выполнение его вполне неожиданно произвело вывод в операторе delete B.

Мой (реальный) вопрос - это: там некоторая неявная 'виртуальность' к оператору delete? Действительно ли это только статично в смысле no-this-pointer? Или это - просто g ++ функция?

Я начал просматривать спецификацию C++, но я должен признать, я был битом, разбитым ею, таким образом, любая ценившая справка.

14
задан Community 23 May 2017 в 12:17
поделиться

2 ответа

Ответ в правилах языка действительно в 12.5 [class.free].

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

12.5/4 говорит, что когда delete не имеет префикса :: , тогда функция освобождения определяется путем поиска delete в контексте динамического типа. виртуальный деструктор. Это обеспечивает поиск, подобный виртуальному, даже несмотря на то, что оператор delete всегда является статической функцией-членом.

Необработанное выделение и освобождение происходит концептуально вне времени существования объекта, поэтому к тому времени, когда должна быть вызвана функция освобождения, уже не существует объекта для обеспечения механизма виртуального поиска, но правила поиска гарантируют, что оператор delete имеет механизм динамического (виртуального облегченного!) Поиска. Это означает, что оператор delete может быть статическим без потери связи с динамическим типом исходного объекта.

17
ответ дан 1 December 2019 в 13:33
поделиться

Оператор delete предназначен только для освобождения памяти, а память освобождается для объекта самого производного класса в целом - за одно действие - точно так же Как и в случае с оператором new , он выделяется для всего самого производного объекта класса - объекта класса, переданного в качестве аргумента в конструкцию new Class .

Вот почему, когда вы выполняете delete ptr; , оператор delete всегда вызывается только один раз для фактического самого производного класса удаляемого объекта и данных о том, какой класс он выводится либо из vtable, если виртуальный деструктор присутствует, либо из типа указателя, если виртуального деструктора нет. Поэтому в операторе delete нет неявной виртуальности - вся виртуальность заканчивается в точке вызова деструктора.

1
ответ дан 1 December 2019 в 13:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: