destructors

C

cronusf

If you have:

#include <iostream>

using namespace std;

class Base
{
public:
~Base()
{
cout << "~Base()" << endl;
}

int x;
};

class Derived : public Base
{
public:
~Derived()
{
cout << "~Derived()" << endl;
}

int y;
int z;
};

int main()
{
Base* b = new Derived;
delete b;
}

Only ~Base() is called, which is expected since it is not virtual.
However, when delete is called, will it free the memory allocated for
the variables y and z?
 
G

george.priv

If you have:

#include <iostream>

using namespace std;

 class Base
{
public:
    ~Base()
        {
                cout << "~Base()" << endl;
        }

    int x;

};

class Derived : public Base
{
public:
        ~Derived()
        {
                cout << "~Derived()" << endl;
        }

    int y;
    int z;

};

int main()
{
    Base* b = new Derived;
    delete b;

}

Only ~Base() is called, which is expected since it is not virtual.
However, when delete is called, will it free the memory allocated for
the variables y and z?

Yes
 
K

Kai-Uwe Bux

If you have:

#include <iostream>

using namespace std;

class Base
{
public:
~Base()
{
cout << "~Base()" << endl;
}

int x;
};

class Derived : public Base
{
public:
~Derived()
{
cout << "~Derived()" << endl;
}

int y;
int z;
};

int main()
{
Base* b = new Derived;
delete b;
}

Only ~Base() is called, which is expected since it is not virtual.
However, when delete is called, will it free the memory allocated for
the variables y and z?

When delete is called you have undefined behavior as per [5.3.5/3]. In
particular, all bets are off with respect to the memory of the variables y
and z.


Best

Kai-Uwe Bux
 
S

Salt_Peter

If you have:

#include <iostream>

using namespace std;

class Base
{
public:
~Base()
{
cout << "~Base()" << endl;
}

int x;

};

class Derived : public Base
{
public:
~Derived()
{
cout << "~Derived()" << endl;
}

int y;
int z;

};

int main()
{
Base* b = new Derived;
delete b;

}

Only ~Base() is called, which is expected since it is not virtual.
However, when delete is called, will it free the memory allocated for
the variables y and z?

No it won't.
If you had used a smart pointer like boost::shared_ptr:

#include "boost/shared_ptr.hpp"

....

int main()
{
boost::shared_ptr< Base > bsp(new Derived);
// no delete needed
}

output:

~Derived()
~Base()
 
K

Kai-Uwe Bux

Salt_Peter said:
No, absolutely not
this test case proves it, ~Derived() is not invoked.

a) The destructor is not involved in freeing the memory for y and z. That
would be an issue for the deallocation function invoked by delete.

b) One has undefined behavior anyway [5.3.5/3] in the test case, so it
proves nothing.


Best

Kai-Uwe Bux
 
A

anon

Kai-Uwe Bux said:
If you have:

#include <iostream>

using namespace std;

class Base
{
public:
~Base()
{
cout << "~Base()" << endl;
}

int x;
};

class Derived : public Base
{
public:
~Derived()
{
cout << "~Derived()" << endl;
}

int y;
int z;
};

int main()
{
Base* b = new Derived;
delete b;
}

Only ~Base() is called, which is expected since it is not virtual.
However, when delete is called, will it free the memory allocated for
the variables y and z?

When delete is called you have undefined behavior as per [5.3.5/3]. In
particular, all bets are off with respect to the memory of the variables y
and z.

Sorry to hijack the tread, but is next example UB as well?

// POD structure
struct A
{
int a;
};

template< typename T >
struct B : public T
{
int b;
};

int main()
{
B< A > *inst = new B< A >;
A &copy = *inst;

inst->b = 2;
copy.a = 3;

delete inst;
}
 
K

Kai-Uwe Bux

anon said:
Kai-Uwe Bux said:
If you have:

#include <iostream>

using namespace std;

class Base
{
public:
~Base()
{
cout << "~Base()" << endl;
}

int x;
};

class Derived : public Base
{
public:
~Derived()
{
cout << "~Derived()" << endl;
}

int y;
int z;
};

int main()
{
Base* b = new Derived;
delete b;
}

Only ~Base() is called, which is expected since it is not virtual.
However, when delete is called, will it free the memory allocated for
the variables y and z?

When delete is called you have undefined behavior as per [5.3.5/3]. In
particular, all bets are off with respect to the memory of the variables
y and z.

Sorry to hijack the tread, but is next example UB as well?

// POD structure
struct A
{
int a;
};

template< typename T >
struct B : public T
{
int b;
};

int main()
{
B< A > *inst = new B< A >;
A &copy = *inst;

inst->b = 2;
copy.a = 3;

delete inst;
}

No undefined behavior that I would see. However, with

A* inst = new B< A >;
...
delete inst;

you would violate [5.3.5/3] as the static type and the dynamic type differ
but the base A does not have a virtual destructor.

BTW: that the types are POD is unrelated.


Best

Kai-Uwe Bux
 
G

george.priv

No, absolutely not
this test case proves it, ~Derived() is not invoked.

Automatic members will be deallocated outside of the user-provided
destructor similar to allocating deallocating by malloc/free. If y, z
would be a pointers allocated within the lifetime of Derived object
and deallocated by Derived::~Derived(), then you will get a memory
leak.

Regards, George
 
S

Salt_Peter

Automatic members will be deallocated outside of the user-provided
destructor similar to allocating deallocating by malloc/free. If y, z
would be a pointers allocated within the lifetime of Derived object
and deallocated by Derived::~Derived(), then you will get a memory
leak.

Regards, George

The members are not automatic:

#include <iostream>

class Member
{
public:
~Member()
{
std::cout << "~Member()" << std::endl;
}
};

class Base
{
Member m;
public:
~Base()
{
std::cout << "~Base()" << std::endl;
}
};

class Derived : public Base
{
Member m;
public:
~Derived()
{
std::cout << "~Derived()" << std::endl;
}
};

int main()
{
Base* p_b = new Derived;

delete p_b;
}

output:

~Base()
~Member()

With virtual ~dtor:

~Derived()
~Member()
~Base()
~Member()
 
G

george.priv

The members are not automatic:

#include <iostream>

class Member
{
public:
  ~Member()
  {
    std::cout << "~Member()" << std::endl;
  }

};

class Base
{
  Member m;
public:
  ~Base()
  {
    std::cout << "~Base()" << std::endl;
  }

};

class Derived : public Base
{
  Member m;
public:
  ~Derived()
  {
    std::cout << "~Derived()" << std::endl;
  }

};

int main()
{
  Base* p_b = new Derived;

  delete p_b;

}

output:

~Base()
~Member()

With virtual ~dtor:

~Derived()
~Member()
~Base()
~Member()

Correct, in your example compiler has no idea that m needs destructor
to be called, but it's memory will be freed nonetheless even without
calling ~Member().

G.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,197
Latest member
ScottChare

Latest Threads

Top