Does "delete" work properly with polymorphism? [duplicate]
Asked Answered
H

2

6
BaseClass * p = new DerivedClass();
delete p;

I know the 2nd line will call the destructor of the base class if it doesn't have a virtual destructor and that of the derived class if it does but will delete properly free the memory (let's say BaseClass's object takes up 8 bytes of space and DerivedClass's one 12 - will it free 8 or 12 bytes) and get rid of the object in either case?

Hovey answered 11/5, 2013 at 14:47 Comment(3)
Are you familiar with malloc/free semantics?Finegrain
Re: " call the destructor of the base class" - maybe. If you delete an object of a derived type through a pointer to a base type and the base type does not have a virtual destructor the behavior is undefined. It might call the destructor for the base class, but it is not required to do that.Hm
@Hovey Note that it is worth to mention that in case you created the DerivedClass object on the stack (i.e. - DerivedClass d;) than it does not matter at all if the BaseClass Dtor is virtual or not - the two of them (both of the Dtor's) will be invoked in a reverse order with respect to the construction of them (i.e. - DerivedClass and than BaseClass ).Peltz
B
8

Well in the case that it has a virtual destructor, of course the object will be destroyed and the memory deallocated as expected. If it doesn't have a virtual destructor, the behaviour is undefined.

if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined.

So it doesn't really make any sense to attempt to reason about whether the memory will be fully deallocated or not. The program can do whatever it likes with the memory.

Bharal answered 11/5, 2013 at 14:50 Comment(0)
T
3

If the destructor isn't virtual, delete won't delete the derived class.

I tried this:

#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;
}

Compiling on G++ 4.7.3 (default optimization), I get

Creating base.
Creating derived.
Killing base.

Note the absence of Killing derived.

Traprock answered 11/5, 2013 at 14:58 Comment(3)
As I understand it, the destructor is only a means of doing manual cleanup before the object is actually destroyed by the program. So, correct me if I'm wrong, but I think this code proves nothing.Hovey
delete both runs the destructor and frees the memory if the memory is allocated on the heap (as it is when you allocate memory using new). If the destructor isn't being called, I think it's safe to say that the memory isn't being freed either.Traprock
@AnubhavC I took your answer further down the line , and added some more points one should consider. In case you are intersted:https://mcmap.net/q/1772184/-c-virtual-destructors-in-a-4-level-inheritance-chainPeltz

© 2022 - 2024 — McMap. All rights reserved.