简体   繁体   中英

Is the whole object freed with a non-virtual destructor and a Base class pointer?

If a Base class does not have a virtual destructor (in order to avoid the vtable entry for instance) and the Derived class has only basic attributes, does it free all the memory allocated by new, when the pointer of the Base class is deleted? I know the destructor of the Derived class will not be called but I am wondering if the memory allocated by the whole object will be freed? I assume also that calling delete on a Derived pointer will free the whole memory space.

Also, if it does not free the Derived class part of the memory, how does it work in the same case but with of a virtual destructor in the Base class, to know how much memory to free ?

Exemple:

class Base {
  public:
    int a;
    int b;
   Base() {}
  ~Base() {}
};

class Derived : public Base {
  public:
    int c;
    int d;
    Derived() {}
    ~Derived() {}
};

int main() {
  Base *p = new Derived();
  delete p; // is memory allocated for Derived freed?
  return 0;
}

It's undefined behavior, so anything can happen. Quote from the standard [expr.delete]:

In the first alternative (delete object), 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.

Although how it works is the detail of implementation, the typical implementation may override automatically the destructor in the derived classes and implement the release of the memory there. Note that you must define the virtual destructor in the base class so the implementation can reserve an entry in the virtual table.

Formally speaking, this is undefined behaviour, so you have no guarantees that the memory is freed, or indeed that your program does anything in particular. It may format your hard disk. It may not. In practice, the memory might well be freed in this case -- but you're daft if you rely on it, and you shouldn't do it. It's as simple as that.

Technically, the answer is 'unknown'. Deleting a pointer to derived from a pointer to base that has no virtual destructor is undefined behavior.

Practically speaking though, most implementations just fail to properly delete the stuff in the derived object.

Edit: I Was mistaken: Key prose from draft standard, emphasis mine: Section 5.3.5

3 In the first alternative (delete object), 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. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

There is a good chance the memory will be correctly freed. Just because the Standard doesn't assure this doesn't mean it won't work. It's hard to see how it could fail.

In the very particular case that you describe, all of the memory used by the derived class object will be freed when you don't have a virtual destructor. (If using non-virtual destructors always caused derived classes to leak memory, I don't think the language would allow inheriting from classes that used them!)

Remember, the DESTRUCTOR is not what frees the memory; "delete" frees the memory. The destructor is just a function that gets CALLED by delete.

Blah blah blah extensibility blah blah cause yourself trouble in the future blah blah careful with that etc. etc. etc. You know what I mean, obviously.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM