Consider this example :
#include <cstdio>
#include <memory>
struct base
{
base( int i ): i(i) { printf("base ctor
"); }
~base() { printf("base non-virtual dtor
"); } // non-virtual
int i;
};
struct derived : public base
{
char* s;
derived(int i): base(i), s(new char[i] )
{
printf("derived ctor
");
}
~derived()
{
printf("derived dtor
");
delete [] s;
}
};
int main()
{
printf("Success
");
//raw pointer
printf("RAW-POINTER
");
{
base* b = new derived(2);
// ......
delete b; //here memory leak, but it's old- and error-prone code.
}
printf("---END-RAW-POINTER--
");
//unique-ptr
printf("UNIQUE_PTR
");
{
// 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--
");
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
");
{
std::shared_ptr<base> b(new derived(3));
}
printf("--END-SHARED_PTR--
");
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.
};
See Question&Answers more detail:os