Betrachten Sie dieses Beispiel:Warum prüft unique-ptr die Basisklasse nicht auf virtual destructible?
#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;
}
Der Code std::unique_ptr<base> bu(new derived(3));
einfach mit std::has_virtual_destructor Typ-Merkmale verbieten. Live code
Warum wird der obige Code kompiliert? Ist das standardmäßig erlaubt?
EDIT: interessant, aber mit std :: shared_ptr gearbeitet, das heißt sowohl Basis- und abgeleitete dtor nennen:
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--
Warum std :: shared_ptr dervied Klasse dtor nennen kann, aber std :: unique_ptr kann nicht ???
EDIT2: simple Ich brauche so etwas wie:
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.
};
@Brian Bi: Nicht alle benutzerdefinierten deleter, in vielen Fällen Benutzer Grenzen mit default_deleter. – Khurshid
'std :: shared_ptr' funktioniert. Es wird den Destruktor der Basis aufgerufen und abgeleitet: http://ideone.com/Nc542V – Brandon
Wenn Sie 'public' Vererbung verwenden, sollten Sie Destruktor als' virtual' definieren. (http://stackoverflow.com/questions/270917/why-should-i-declare-a-virtual-destructor-for-an-abastract-class-in-c) – zahir