In the code below, why is the ~Derived() destructor called automatically?
#include<iostream>
using namespace std;
class Base
{
public:
virtual ~Base()
{
cout << "Calling ~Base()" << endl;
}
};
class Derived: public Base
{
private:
int* m_pnArray;
public:
Derived(int nLength)
{
m_pnArray = new int[nLength];
}
virtual ~Derived()
{
cout << "Calling ~Derived()" << endl;
delete[] m_pnArray;
}
};
int main()
{
Derived *pDerived = new Derived(5);
Base *pBase = pDerived;
delete pBase;
return 0;
}
Because your base class destructor is virtual
virtual ~Base();
the call to delete on a pointer to a base class results in virtual call to destructor and as any virtual call is dispatched to matching function in derived class. It is not only good, but necessary: otherwise the behavior is undefined.
This is crucial for a derived classes which destructor is not an empty function. Non-virtual call would otherwise result in calling base class destructor, derived resources being leaked, etc.
When you have at least one virtual function in a class, then the compiler creates a single table for the class listing the member function pointers. Consider:
struct Base
{
virtual ~Base() { };
int n_;
};
In pseudo-code you can imagine the compiler adding:
void* Base::__virtual_dispatch_table[] = { (void*)&Base::~Base };
Then, when you have an actual object of type Base it will have an extra hidden data member that points to the Base::__virtual_dispatch_table (the "VDT"):
Variable definition Memory layout
------------------- -------------
Base myBase; int n_;
void** __p_vdt = Base::__virtual_dispatch_table;
Now, if you have a Base* p and delete p;, the compiler says "hey - it's virtual - I won't hardcode a call to Base::~Base, instead I'll generate code that does something like this pseudo-code:
void (Base::*p_destructor) = p->__p_vdt[0]
*p_destructor(p); // "p" will provide the "this" value while the destructor runs
Why would you want to do all that? Because when you come along with a Derived object...
class Derived: public Base
{
private:
int* m_pnArray;
...
...the compiler can create a separate virtual dispatch table...
void* Derived::__virtual_dispatch_table[] = { (void*)&Derived::~Derived };
...andd lay out the Derived object's memory like this:
Variable definition Memory layout
------------------- -------------
Derived derived; int n_;
void** __p_vdt = Derived::__virtual_dispatch_table;
int* m_pnArray;
Notice that the __p_vdt is in the same relative location within the object layout, but now points to the Derived class's virtual dispatch table?
Now, if you create a Base* to derived, the exact same code needed to call the destructor for a Base object, which - in case you've lost track - was...
void (Base::*p_destructor) = p->__p_vdt[0]
*p_destructor(p); // "p" will provide the "this" value while the destructor runs
...can be run but will end up using the Derived object's __p_vdt value of Derived::__virtual_dispatch_table, and finding the Derived class's destructor.
Because it allows you to treat any Base object (which may in fact be a Derived) as an object that you can delete.
In this case, if delete pBase didn't call the Derived destructor, the data held by m_pnArray would never get deleted, i.e. a "memory leak" would occur.
When you call
delete pBase;
It looks at the virtual function table of pBase to find the appropriate destructor to begin unwinding at, and it finds Derived::~Derived and then works its way down the stack.
Related
Are destructors required to be virtual when implementing curiously recurring template pattern (CRTP)? And if not, what is the proper non-virtual implementation?
I'll provide an example to hopefully make things easier:
template<typename T>
class Base
{
public:
virtual ~Base()
{
// Should this be virtual? Non-virtual?
std::cout << "Base::~Base()\n";
}
};
class Derived : public Base<Derived>
{
public:
~Derived() override
{
std::cout << "Derived::~Derived()\n";
}
};
int main()
{
Base<Derived>* b = new Derived;
delete b;
}
Result:
Derived::~Derived()
Base::~Base()
(Live Sample Here)
EDIT: Updated the example to use runtime polymorphism so that the virtual destructor is required for proper cleanup.
A CRTP base class is no different from any other base class in this sense. You will need a virtual destructor only if you are going to delete an object of type Derived via a pointer to Base<Derived>. Otherwise, a virtual destructor is not required.
Base<Derived>* b = new Derived;
delete b; // Base<Derived>::~Base<Derived> must be virtual
In the example you showed, a virtual destructor is not needed. A virtual destructor is just needed when you may need to call it using a pointer to the base class, the same as an overriden function must be virtual in this case. And in the case of a CRTP class like you showed, there is rarely a need to delete a Base<T> instead of T itself.
int main()
{
Derived *a = new Derived();
// we have the right type anyway, so dont actually need a virtual anything (even normal virtual methods)
delete a;
Derived *a = new Dervied();
Base<Derived> *b = a;
// We are now deleting via a parent class, so this needs a virtual destructor.
// This is pretty uncommon with a simple CRTP however.
delete b;
}
If you're going to call delete on a pointer of a base class that's pointing to a derived object then you need a virtual destructor, that's all there is to it. CRTP or no CRTP.
I believe It's C++ but it may be C? Its been a while since I looked at C++ so I didn't end up finding the bug. I was asked this question in an interview and didn't have an answer. I obviously didn't get the job but now I'm curious to find the answer.
#include<iostream>
class Base {
public:
Base() {
std::cerr<<"constructing Base " << this << std::endl;
i = new int;
}
~Base() {
std::cerr<<"destroying Base " << this << std::endl;
delete i;
}
private
int* i;
};
class Derived : public Base {
public:
Derived() {
std::cerr<<"constructing Dervied " << this << std::endl;
d = new double;
}
~Derived() {
std::cerr<<"destroying Derived " << this << std::endl;
delete d;
}
private
double* d;
};
int main(int argc, char** argv) {
using namespace std;
int ret = 1;
Base* thePtr = new Derived;
delete thePtr;
return ret;
}
Thanks in advance!
The Base's destructor is not virtual. This will leak the Derived::d pointer, at best.
Actually, it's undefined behaviour to delete a pointer of derived class through a base class pointer without virtual destructor (thanks to GManNickG)
You should mark Base class destructor as virtual. In your code Base class destructor isn't virtual & base class pointer is pointing to Derived class object so by default destructor will be called of Base class unless it is marked as virtual. This will leak dynamically allocated memory of Derived class data member d & invokes undefined behaviour.
Let me make a list...
Base destructor is not virtual.
It's using raw pointers instead of smart pointers
In fact, it doesn't need pointers, new and delete at all
And therefore, it doesn't actually need destructors.
Also Derived is spelled Dervied
... and it won't compile.
Your base class destructor should be declared virtual, it looks like
cpp
virtual ~Base()
{
std::cerr<<"destroying Base " << this << std::endl;
delete i;
}
you can find it here http://www.programmerinterview.com/index.php/c-cplusplus/virtual-destructors/
Virtual destructors are useful when you can delete an instance of a derived class through a pointer to base class:
there is a major problem with the code above: the destructor for the "Derive" class does not get called at all when we delete basePtr,
The construction of derived object follow the construction rule but when we delete the "b" pointer(base pointer) we have found that only the base destructor is call.But this must not be happened.
To do the appropriate thing we have to make the base destructor virtual. it's similar to the run-time polymorphism, so that the compiler will find this is a base pointer but point to the derived class, and automatically bound derived class destructor for it
I have a class hierarchy that's three levels deep, like this:
class A {
public:
virtual ~A() {}
}
class B : public A {
public:
virtual ~B() {}
void foo(E *e) {
e->remove(this);
}
}
class C : public B {
public:
~C() {}
}
class E {
public:
void remove(A *a) {
delete a;
}
}
Ok so what I am wondering is what happens when I call foo() on an object of C. Is it going to remove the entire object or only the B and A part of the object, and leave the C part still in memory?
Is it going to remove the entire object or only the B and A part of the object, and leave the C part still in memory?
No. It will "do the right thing" (that is, delete the most derived subobject, run all its destructors etc.) provided A (that is, the static type of the pointee of the pointer you delete) has a virtual destructor (and if class A has a virtual destructor, all its descendants have it, too). This holds for multiple inheritance, too.
Thanks to the virtual destructor in A the code would work correctly destroy the entire instance of C.
delete will always release the memory for the whole object pointed to.
This doesn't apply to called destructors however: It will try to call the destructor of the static type of the object to delete.
In a polymorphistic scenario, this is often not what you want. Consider this:
struct Base { };
struct Derived : Base
{
int* i;
Derived() : i(new int) { }
~Derived() { delete i; }
}
void bad()
{
Base* b = new Derived;
delete b;
}
bad() causes a memory leak, because Deriveds destructor will never be called. This is because the static type of b is Base*, thus Base::~Base will be called. There is no destructor defined in Base, so the default implementation provided by the compiler executes, which does nothing in this particular example.
This however does not apply to your example: You made the root class' destructor virtual, so all derived classes' destructors will be executed as part of the destructor call.
I've had some second thoughts on multiple virtual destructors, esp. after reading reading http://blogs.msdn.com/b/oldnewthing/archive/2004/05/07/127826.aspx .
Suppose I have
class Base
{
public:
Base();
virtual ~Base();
private:
Logger* _logger;
};
//and
class Derived : public Base{
public:
Derived();
virtual ~Derived();
private:
Logger* _logger;
};
in the cpp files, in each destructor I am deleting the respective _logger pointers
Base::~Base(){ //base.cpp
delete _logger;
}
Derived::~Derived(){ //derived.cpp
delete _logger;
}
will this work as I intended, without memory leaks?
First off, if you make the base class destructor virtual, all derived classes will automatically get a virtual destructor if you declare them as virtual or not. This is generally true for matching signatures: if a base class has a virtual function with the same signature as a function in a derived class, the function in the derived class is an override and is virtual (although in C++ 2011 you can prevent further overriding using the final keyword in which case another override would create an error).
That said, destructors are special: when you make a destructor virtual it will still be called even if there is another overriding destructor! The only impact of a destructor being virtual is what happens if you delete an object using a pointer to a base class when the object actually happens to be of a derived type: If the destructor isn't virtual you get undefined behavior while the Right Thing happens if the destructor is virtual. For example:
class not_a_base {};
class bad_idea: public not_a_base {};
class a_base { public: virtual ~a_base() {} };
class ok: public a_base {};
int main() {
a_base* ab = new ok;
delete ab; // <---- all is good here!
not_a_base* nab = new bad_idea;
delete nab; // <---- results in undefined behavior
}
The reason destructors are not virtual by default is simply that this would mean that object size is always increased by a word size which is unacceptable in general.
Base::_logger is a different variable then Derived::_logger. So you should delete Derived::_logger in Derived's dctor, or else you leak memory.
Note that this has nothing to with it being private. Consider this example program:
#include <iostream>
class A {
public:
bool foo;
};
class B: public A {
public:
bool foo;
};
int main()
{
B b;
std::cout << &b.B::foo << ' ' << &b.A::foo << '\n';
}
The addresses are different. That means they're different variables, even though they have the same name. This is possible since each class introduces its own namespace, so the names don't really clash. The first is A::foo, the other one B::foo.
Since your destructors are virtual, both will get called, and the correct _logger will be deleted in both of them.
Suppose I have this code
class Base{
public:
int getVal();
private:
int a, b;
};
class Derived::public Base{
public:
void printVal();
};
int main(){
Base *b = new Derived();
delete b;
}
I know a virtual destructor would delete things properly, but is it bad to delete with base pointer (when there is no virtual destructor) even if there are no virtual functions and no data members in the derived class? What will happen if this is done?
Is it bad to delete with base pointer (when there is no virtual destructor) even if there are no virtual functions and no data members in the derived class?
Yes.
The behavior is undefined regardless the contents of the derived class.
What will happen if this is done?
Anything could happen.
For primitive-type data, your example will most likely work in practice. As a matter of fact, incurring a vtable could actually hinder performance (so there may be some legitimate use here), but it is technically undefined, per 5.3-5.4:
If the static type of the operand [of
the delete operator] is different from
its dynamic type, the static type
shall be a base class of the operand's
dynamic type and the static type shall
have a virtual destructor or the
behaviour is undefined.
It really all depends on the "heapness" of the data in your class, and as there are no heap-allocated members (in your case), you should be fine, but it's definitely a code smell.
The virtual desctructor in the derived class is needed in order to properly call the derived destructor (polymorphism), when the derived object is created through a pointer to the base class.
High Integrity CPP Rule 3.3.2 Write a 'virtual' destructor for base classes. (QACPP 2116)
Justification: If an object will ever be destroyed through a pointer to its base class, then that base class should have a virtual destructor. If the base class destructor is not virtual, only the destructor for the base class will be invoked. In most cases, destructors should be virtual, because maintenance or reuse may add derived classes that require a virtual destructor.
class Base {};
class Derived : public Base { public: ~Derived() {} };
void foo() {
Derived* d = new Derived; delete d; // correctly calls derived destructor
}
void boo() {
Derived* d = new Derived; Base* b = d; delete b; // problem! does not call derived destructor!
}