Определение правильного формата деструктора в С++

Я столкнулся с этим вопросом:

данный класс А:
class A {
public:
         int size, ** x, *** y;
         A(int _size) {
             size = _size;
             x = new int* [size];
             y = new int** (x);
             for (int i = 0; i < size; i++)
                 x[i] = new int(size);
     }
};
определить правильные деструкторы

Есть пять вариантов:

1
~A() {
     for (int i = 0; i < size; i++)
         delete x[i];
     delete [] x;
     delete y;
}
2
~A() {
     delete y;
     for (int i = 0; i < size; i++)
         delete x[i];
     delete[] x;
}
3
~A() {
     delete y;
     delete [] x;
     for (int i = 0; i < size; i++)
         delete x[i];
}

4
~A() {
     delete [] x;
     for (int i = 0; i < size; i++)
         delete x[i];
     delete y;
}
5
~A() {
     for (int i = 0; i < size; i++)
         delete x[i];
     delete y;
     delete [] x;
}

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

Однако правильный ответ — любой из деструкторов с номерами 1,2,5.

Насколько я понимаю, операнд удаления освобождает память по адресу, на который указывает указатель, поэтому, если мы удалим объект y перед объектом x[], то в x можно будет записать что угодно, и мы не сможем удалить эту информацию, потому что мы не т знаю, что это такое.

Я прав в своем понимании?

Можете ли вы дать мне представление о том, почему деструкторы 2 и 5 жизнеспособны?

А если 2,5 жизнеспособны то почему не 3 и 4?

6) используйте правильные типы для членов, которые инкапсулируют управление памятью и позволяют вам следовать правилу 0, то есть ~A() {};

463035818_is_not_a_number 22.02.2023 11:47
*y содержит значение x; между указателями y и x нет никакой связи. delete Делать y первым так же безопасно, как { int x = 1; int* y = new int(x); delete y; }.
molbdnilo 22.02.2023 11:57
int size, ** x, *** y - это бесполезное использование указателей... В C++ не используйте new/delete, если вам это не нужно. Посмотрите на std::vector и что вы можете с этим сделать. Где вы изучаете С++? ваш источник кажется устаревшим. (С текущим С++ вам даже не придется сталкиваться с проблемами, которые у вас возникают)
Pepijn Kramer 22.02.2023 12:00
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц....
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
Запуск PHP на IIS без использования программы установки веб-платформы
Запуск PHP на IIS без использования программы установки веб-платформы
Установщик веб-платформы, предлагаемый компанией Microsoft, перестанет работать 31 декабря 2022 года. Его закрытие привело к тому, что мы не можем...
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
1
3
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

После того, как вы удалили x, вы больше не можете получить доступ к x[i]. Это исключает 3 и 4.

Порядок удаления y и x, с другой стороны, не имеет значения. Здесь:

 y = new int** (x);

Вы динамически выделяете y и инициализируете его значением x. Это означает x == *y, это единственная связь между ними.

Деструктор, к которому вы действительно должны стремиться, это

~A() {}

Управление памятью — отдельная задача. Достаточно сделать 1 класс. Управление двумя ресурсами уже слишком много для одного класса. Вы можете написать обертки для членов, чтобы правильно управлять памятью, чтобы самому A не нужно было с ней возиться. Однако эта проблема уже решена. Есть умные указатели и контейнеры, вам просто нужно их выбрать и использовать. Я предлагаю сначала взглянуть на std::vector, так как он охватывает большинство вариантов использования.

Вас смущают int **x и int ***y; Обратите внимание, что в вашем примере результаты x и *y одинаковы, но delete y не влияет на x, поэтому вы можете делать это в любом порядке. Важно только delete x[i] до delete[] x;

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

Другие вопросы по теме