http://en.cppreference.com/w/cpp/memory/unique_ptrIf T is a derived class of some base B, then std::unique_ptr<T> is implicitly convertible to std::unique_ptr<B>. The default deleter of the resulting std::unique_ptr<B> will use operator delete for B, leading to undefined behavior unless the destructor of B is virtual. Note that std::shared_ptr behaves differently: std::shared_ptr<B> will use the operator delete for the type T and the owned object will be deleted correctly even if the destructor of B is not virtual.
Dla porządku:
Jak nie dodasz virtual dla destruktora klasy bazowej, to tak w 1 (dostęp przez wskaźnik) jak i w 2 przypadku (dostęp przez unique_ptr), masz zachowanie niezdefiniowane UB (ang. Undefined Behavior). Dla dostępu przez unique_ptr, kompilator nie zgłasza ostrzeżenia bo domyślny destruktor który występuje w szablonie unique_ptr, zapisany jest w plikach nagłówków systemowych. Jeśli chcesz by zgłaszał, dodaj do ostrzeżeń -Wsystem-headers. Informacja o braku virutal będzie jednym z ostrzeżeń.
Kod: Zaznacz cały
#include <memory>
#include <iostream>
struct Bazowa {
virtual void przywitaj() {
std::cout << "z klasy bazowej\n";
}
};
struct Pochodna : public Bazowa {
virtual void przywitaj() override {
std::cout << "z klasy pochodnej\n";
}
};
int main() {
// Przypadek 1 ze wskaźnikiem.
Bazowa *b = new Pochodna;
b->przywitaj();
delete b;
// Przypadek 2 z unique_ptr
std::unique_ptr<Bazowa> sb = std::make_unique<Pochodna>();
sb->przywitaj();
}Kompilacja:
Kod: Zaznacz cały
g++ -Wall -Wextra -std=c++14 -o plik plik.cppOstrzeżenie:
Kod: Zaznacz cały
plik.cpp: In function 'int main()':
plik.cpp:20:12: warning: deleting object of polymorphic class type 'Bazowa' which has non-virtual destructor might cause undefined behaviour [-Wdelete-non-virtual-dtor]
delete b;Kompilacja:
Kod: Zaznacz cały
g++ -Wall -Wextra -Wsystem-headers -std=c++14 -o plik plik.cppOstrzeżenia (większość to o deprecated auto_ptr):
I
Kod: Zaznacz cały
n file included from /opt/local/include/gcc5/c++/memory:81:0,
from plik.cpp:1:
/opt/local/include/gcc5/c++/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = Pochodna]':
/opt/local/include/gcc5/c++/bits/unique_ptr.h:236:17: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = Pochodna; _Dp = std::default_delete<Pochodna>]'
plik.cpp:23:61: required from here
/opt/local/include/gcc5/c++/bits/unique_ptr.h:76:2: warning: deleting object of polymorphic class type 'Pochodna' which has non-virtual destructor might cause undefined behaviour [-Wdelete-non-virtual-dtor]
delete __ptr;
^
/opt/local/include/gcc5/c++/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = Bazowa]':
/opt/local/include/gcc5/c++/bits/unique_ptr.h:236:17: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = Bazowa; _Dp = std::default_delete<Bazowa>]'
plik.cpp:23:61: required from here
/opt/local/include/gcc5/c++/bits/unique_ptr.h:76:2: warning: deleting object of polymorphic class type 'Bazowa' which has non-virtual destructor might cause undefined behaviour [-Wdelete-non-virtual-dtor]