2013-05-11 2 views
3
BaseClass * p = new DerivedClass(); 
delete p; 

Я знаю, что вторая линия будет вызывать деструктор базового класса, если он не имеет виртуальный деструктор и что производный класс, если он делает, но будет delete правильно освободить память (скажем BaseClass «s объект занимает 8 байтов пространства и DerivedClass - один из 12 - освободит ли он 8 или 12 байтов) и избавится от объекта в любом случае?«Удаляет» работу с полиморфизмом?

+0

Вы знакомы с 'malloc'/'free' семантика? –

+1

Re: «вызвать деструктор базового класса» - может быть. Если вы удаляете объект производного типа с помощью указателя на базовый тип, а базовый тип не имеет виртуального деструктора, поведение не определено. Он может вызвать деструктор для базового класса, но от этого не требуется. –

+0

@NPS Обратите внимание, что стоит упомянуть, что если вы создали объект DerivedClass в стеке (т.е. - DerivedClass d;), то это не имеет значения, если BaseClass Dtor является виртуальным или нет - два из них (оба от Dtor's) будут вызваны в обратном порядке относительно их построения (т.е. - DerivedClass и BaseClass). –

ответ

5

Ну, в случае, если у него есть деструктор virtual, конечно же объект будет уничтожен, а память освободится, как и ожидалось. Если он не имеет деструктора virtual, поведение не определено.

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

Так что на самом деле не имеет смысла пытаться рассуждать о том, будет ли память полностью освобождена или нет. Программа может делать все, что угодно, с памятью.

2

Если деструктор не является виртуальным, delete не удаляет производный класс.

Я попытался это:

#include<iostream> 

using namespace std; 

class Base { 
public: 
    Base() { 
     cout<<"Creating base."<<endl; 
    } 

    ~Base() { 
     cout<<"Killing base."<<endl; 
    } 
}; 

class Derived: public Base { 
public: 
    Derived() { 
     cout<<"Creating derived."<<endl; 
    } 

    ~Derived() { 
     cout<<"Killing derived."<<endl; 
    } 
}; 

int main() { 
    Base *p = new Derived(); 
    delete p; 
    return 0; 
} 

Компиляция на G ++ 4.7.3 (оптимизация по умолчанию), я получаю

Creating base. 
Creating derived. 
Killing base. 

Обратите внимание на отсутствие Killing derived.

+0

Как я понимаю, деструктор - это только средство ручной очистки до того, как объект ** фактически уничтожен программой **. Итак, поправьте меня, если я ошибаюсь, но я думаю, что этот код ничего не доказывает. – NPS

+0

['delete' обе запускает деструктор и освобождает память] (http://stackoverflow.com/a/677661/1321855), если память выделена в куче (так же, как если вы выделяете память с помощью' new') , Если деструктор не вызывается, я думаю, что можно с уверенностью сказать, что память также не освобождается. –

+0

@AnubhavC Я принял ваш ответ дальше по линии и добавил еще несколько моментов, которые следует рассмотреть. Если вы заинтересованы: http: //stackoverflow.com/a/41801254/1971003 –