std::unique_ptr i wirtualny destruktor
std::unique_ptr i wirtualny destruktor
Witam, czy dla std::unique_ptr wymagany jest wirtualny destruktor jeśli mamy klasy pochodne? Dla zwykłego wskaźnika na klasę bazową otrzymuje ostrzeżenie, że go nie posiadam, a dla std::unique_ptr już nie, choć też powinno być, skoro wskazuje na klasę bazową.
- mokrowski
- User
- Posty: 190
- Rejestracja: czwartek 08 paź 2015, 20:50
- Lokalizacja: Tam gdzie Centymetro
Re: std::unique_ptr i wirtualny destruktor
http://en.cppreference.com/w/cpp/memory/unique_ptr
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ń.
Kompilacja:
Ostrzeżenie:
Kompilacja:
Ostrzeżenia (większość to o deprecated auto_ptr):
I
If 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.cpp
Ostrzeż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.cpp
Ostrzeż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]
,,Myślenie nie jest łatwe, ale można się do niego przyzwyczaić" - Alan Alexander Milne: Kubuś Puchatek
Re: std::unique_ptr i wirtualny destruktor
Dzięki, wątpliwości rozwiane
Wróć do „Pisanie programów w C++”
Kto jest online
Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 2 gości