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

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

данный класс А:

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
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
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.

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