C++ вызов деструктора при изменяющимся типе

Рейтинг: 0Ответов: 2Опубликовано: 23.04.2023

Столкнулся с проблемой вызова деструктора в структуре, где тип данных может меняться. Чтобы удалить переменную 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". Как написать чтобы работало во всех случаях?

Ответы

▲ 0Принят

У вас прямые вызовы конструктора и деструктора.

S<B*> s = S<B*>();
s.~S();

Это делать не надо, так как всё делается автоматически. В полях структур тоже будет вызван деструктор.
"если переменной, то delete &b" - не надо.

S<B*> s;

Делать шаблонный объект из указателя не желательно, так как удаление объекта, заданного указателем не будет вызвано автоматически. А в шаблонах не реализовано иметь разные функции, в зависимости от того, тип указатель или нет.
Хорошим выходом будет использовать только умные указатели, в деструкторе которых удаление указателя будет вызвано автоматически.

S < std :: unique_ptr < B > > s2 ;
s2 . b . reset ( new D ) ;
▲ 1
  1. s.~S() писать не надо, это происходит автоматически.

  2. Если 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 и деструкторы - дурной тон, если только вы не пишете свой контейнер или умный указатель.