Consider this example :
#include <cstdio>
#include <memory>
struct base
{
base( int i ): i(i) { printf("base ctor\n"); }
~base() { printf("base non-virtual dtor\n"); } // non-virtual
int i;
};
struct derived : public base
{
char* s;
derived(int i): base(i), s(new char[i] )
{
printf("derived ctor\n");
}
~derived()
{
printf("derived dtor\n");
delete [] s;
}
};
int main()
{
printf("Success\n");
//raw pointer
printf("RAW-POINTER\n");
{
base* b = new derived(2);
// ......
delete b; //here memory leak, but it's old- and error-prone code.
}
printf("---END-RAW-POINTER--\n");
//unique-ptr
printf("UNIQUE_PTR\n");
{
// I would that, this doesn't compile, because base- has not virtual destructor.
std::unique_ptr<base> bu( new derived(3) ); // here still memory leak !!!!
}
printf("--END-UNIQUE_PTR--\n");
return 0;
}
The code std::unique_ptr<base> bu( new derived(3) );
easy prohibit with std::has_virtual_destructor type-traits.
Live code
So why does above code compiled? Is this allowed by standard ?
EDIT: interesting, but with std::shared_ptr worked, i.e. both base and derived dtor will call:
printf("SHARED_PTR\n");
{
std::shared_ptr<base> b(new derived(3));
}
printf("--END-SHARED_PTR--\n");
Output:
SHARED_PTR
base ctor
derived ctor
derived dtor
base non-virtual dtor
--END-SHARED_PTR--
Why std::shared_ptr can call dervied class dtor, but std::unique_ptr can't ???
EDIT2: simple I need something like:
template< typename T, typename D = default_deleter<T> >
class unique_ptr{
.............
template< typename U >
unique_ptr( U* u ) if ( U != T && T - is class && T is base of U, and D - is default_deleter, and T - has not virtual destructor ) then = delete this ctor.
};
std::shared_ptr
will work. It will call the destructor of base and derived: ideone.com/Nc542V – Imposepublic
inheritance, you should define destructor asvirtual
. (#271417) – Loamp
where the static type of*p
is different from the dynamic type is Undefined Behaviour, but not forbidden (= not ill-formed). Also, you'd have to check in the dtor ofunique_ptr
, as you can supply incomplete types as long as they're complete at the point of instantiation of the dtor ofunique_ptr
(or their dtor is trivial). – Plead