C++ вызов деструктора при изменяющимся типе
Столкнулся с проблемой вызова деструктора в структуре, где тип данных может меняться. Чтобы удалить переменную b в структуре надо явно прописать это в деструкторе. Если T будет указателем, то надо писать delete b, если переменной, то delete &b.
class B {
public:
virtual ~B() { cout<<"B"; }
};
class D : virtual public B {
public:
~D() { cout<<"D"; }
};
template <typename T>
struct S {
S() {}
T b;
~S() { cout<<"S"; }
};
int main() {
S<B*> s = S<B*>();
s.b = new D;
s.~S(); //выводит только "S"
return 0;
}
Если запустить код то выведется только "S". Как написать чтобы работало во всех случаях?
Ответы (2 шт):
У вас прямые вызовы конструктора и деструктора.
S<B*> s = S<B*>();
s.~S();
Это делать не надо, так как всё делается автоматически. В полях структур тоже будет вызван деструктор.
"если переменной, то delete &b" - не надо.
S<B*> s;
Делать шаблонный объект из указателя не желательно, так как удаление объекта, заданного указателем не будет вызвано автоматически. А в шаблонах не реализовано иметь разные функции, в зависимости от того, тип указатель или нет.
Хорошим выходом будет использовать только умные указатели, в деструкторе которых удаление указателя будет вызвано автоматически.
S < std :: unique_ptr < B > > s2 ;
s2 . b . reset ( new D ) ;
s.~S()писать не надо, это происходит автоматически.-
Если
Tбудет указателем, то надо писатьdelete b, если переменной, тоdelete &b.delete &bделать не надо, потому чтоbне был бы создан черезnew.Для
delete bможно было бы сделать вот так:if constexpr (std::is_pointer_v<T>) delete b;Но самом деле лучше ничего в деструктор
Sне добавлять, а как вам правильно советуют, вместо сырого указателя использовать умный:S<std::unique_ptr<B>> s; s.b = std::make_unique<D>();.Вообще, звать руками
new,deleteи деструкторы - дурной тон, если только вы не пишете свой контейнер или умный указатель.