Должен ли я освободить все члены (которые были динамически выделены) в деструкторе?

#include <iostream>
#include <vector>
using namespace std;
#define l(x) cout << (#x) << " : " << x << endl;
#define forf(x, fromY, Step, toZ) for(double x = fromY; x <= toZ; x+=Step)

class Particle {
public:
    Particle() {
        totalYield = winRate = 0;
    }
    ~Particle() {
        //cout << " Particle destructor were called";
        args.~vector();
    }
    Particle(double* inputArgs, int nSize) 
    :args(nSize)
    {
        for (int i = 0; i < nSize; i++) {
            args[i] = inputArgs[i];
        }
        totalYield = winRate = 0;
    }
    double GetAt(int i = 0) {
        return args[i];
    }

protected:
    double winRate, totalYield;
    unsigned int winCount, totalCount;
    vector<double> args;
};

Здравствуйте, я узнал из своего учебника, что я должен освободить всю память после использования динамического распределения.

Из того, что я узнал, деструктор вызывает деструкторы членов по умолчанию (без какой-либо команды)

  1. Мой первый вопрос: если я использую динамически выделяемый массив в классе, должен ли я освобождать их в деструкторе?. Это неясно, потому что деконструктор, естественно, по умолчанию вызывает деструктор своих членов. освобождает ли это выполнение динамически выделенную память?
  2. Мой второй вопрос: должен ли я вызывать деструктор вектора-члена в деструкторе класса? (см. args.~vector(); // я должен это сделать? это правильно?)

person Antonio SEO    schedule 03.09.2018    source источник
comment
Ничто в вашем классе не выделяется явно динамически (vector - это не то же самое, что динамически выделяемый массив; это самоуправляемая вещь, подобная массиву, поэтому она очищается после себя). Здесь нечего разрушать; деструктор по умолчанию подойдет.   -  person ShadowRanger    schedule 03.09.2018
comment
деконструктор — это слово деструктор, а не деконструктор.   -  person PaulMcKenzie    schedule 03.09.2018
comment
Должен ли я вызывать деконструктор вектора-члена в деконструкторе класса? -- Вы не только не должны делать это в деструкторе, вы не должны делать этого нигде, если только вы не используете placement-new .   -  person PaulMcKenzie    schedule 03.09.2018
comment
Не пытайтесь вручную вызывать деструкторы   -  person M.M    schedule 03.09.2018
comment
@ShadowRanger Спасибо! Вы имеете в виду, что мне не нужно вызывать деконструктор вектора? а затем класс Particle автоматически вызывает ~vector?   -  person Antonio SEO    schedule 03.09.2018
comment
@AntonioSEO: Да, и да. Весь смысл дизайна RAII C++ в сочетании с Правилом нуля заключается в следующем. что, если вы не пишете свой собственный класс, который существует исключительно для управления ресурсом, вам не нужно писать собственные деструкторы (среди прочего), потому что C++ сделает это за вас.   -  person ShadowRanger    schedule 03.09.2018


Ответы (1)


если я использую динамически выделенный массив в классе, должен ли я освобождать их в деконструкторе?

Если ваш класс выделяет память, то ваш класс должен ее освободить. Если класс динамического массива выделяет память, то этот класс динамического массива должен освободить память.

деконструктор, естественно, по умолчанию вызывает деконструкторы своих членов. освобождает ли это выполнение динамически выделенную память?

Давайте посмотрим, что говорит ссылка на деструктор std::vector:

Разрушает контейнер. Вызываются деструкторы элементов и освобождается используемая память.

Получается, что да, память действительно освобождается. Это хороший дизайн для контейнера.


Должен ли я вызывать деконструктор вектора-члена в деконструкторе класса? (См. args.~vector(); // Должен ли я это сделать? Это правильно?)

Нет, не надо, это неправильно. Потому что, как вы сказали, "деконструктор вызывает деконструкторы членов по умолчанию". Чтобы уточнить, члены всегда уничтожаются после выполнения тела деструктора. Если вы также вызываете деструктор члена внутри тела деструктора, то этот деструктор будет вызываться дважды, что очень плохо.

Неявный деструктор правильный и достаточный для вашего класса. Вам не нужно определять это явно.

Вряд ли когда-либо потребуется явно вызывать деструктор. Деструкторы базовых подобъектов и членов вызываются автоматически при уничтожении суперобъекта. Деструкторы элементов массива вызываются автоматически при уничтожении массива. Деструкторы автоматических объектов вызываются автоматически, когда автоматический объект выходит за пределы области видимости. Деструкторы динамических объектов вызываются автоматически при выражении delete. Деструкторы статических объектов вызываются автоматически во время статического уничтожения, которое происходит после возврата функции main. Ни в одном из этих случаев нет необходимости явно вызывать деструктор.

Единственный случай, когда требуется явный вызов деструктора, — это ситуации, когда хранилище объектов повторно используется для других объектов — это продвинутая техника, которую вам пока не нужно изучать.

person eerorika    schedule 03.09.2018
comment
Очень подробный ответ! Спасибо. Я не буду вызывать деструкторы члена, если я динамически не выделил новую память. - person Antonio SEO; 03.09.2018
comment
@AntonioSEO нет, не вызывайте деструкторы члена, если вы также динамически выделяете новую память. Пусть выражение delete вызывает деструкторы. - person eerorika; 03.09.2018
comment
О да, это было то, что я пытался сказать. Я буду использовать только оператор удаления! Спасибо ^^ - person Antonio SEO; 03.09.2018