C++ удаление указателя на указатель

Итак, у меня есть указатель на массив указателей. Если я удалю это так:

delete [] PointerToPointers;

Удалит ли это все указатели на указатели? Если нет, мне нужно перебрать все указатели и удалить их, или есть более простой способ сделать это? Мой гугл-фу, похоже, не дает мне хороших ответов на этот вопрос.

(И да, я знаю, что мне нужно использовать вектор. Это одно из тех присваиваний типа "наверстать упущенное в C++" в школе.)

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
21
0
29 122
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Я думаю, тебе придется перебрать петлю, боюсь.

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

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

Да, вам нужно перебирать указатели, удаляя индивидуально.

Причина: что, если бы в другом коде были указатели на объекты в вашем массиве? Компилятор C++ не знает, правда это или нет, поэтому вы должны быть явным.

В качестве «более простого способа» два предложения: (1) Создайте подпрограмму для этой цели, чтобы вам, по крайней мере, не приходилось писать код более одного раза. (2) Используйте парадигму проектирования «интеллектуального указателя», в которой вы храните массив объектов со счетчиками ссылок, а затем объекты удаляются, когда на них больше не ссылается какой-либо код.

Я согласен с Джейсоном Коэном, хотя мы можем немного пояснить причину необходимости удаления указателей с помощью цикла. Для каждого «нового» или динамического выделения памяти должно быть «удаление» освобождения памяти. Иногда «удалить» можно скрыть, как в случае со смарт-указателями, но оно все еще присутствует.

int main()
{
  int *pI = new int;
  int *pArr = new int[10];

пока что в коде мы выделили два блока динамической памяти. Первый - это просто общий тип int, второй - массив целых чисел.

  delete pI;
  delete [] pArr;

эти операторы удаления очищают память, выделенную "новыми"

  int ppArr = new int *[10];

  for( int indx = 0; indx < 10; ++indx )
  {
    ppArr[indx] = new int;
  }

Этот фрагмент кода выполняет оба предыдущих распределения. Сначала мы создаем пространство для нашего int в динамическом массиве. Затем нам нужно перебрать и выделить int для каждого места в массиве.

  for( int indx = 0; indx < 10; ++indx )
  {
    delete ppArr[indx];
  }
  delete [] ppArr;

Обратите внимание на порядок, в котором я выделял эту память, а затем отменял ее в обратном порядке. Это потому, что если бы мы сделали delete [] ppArr; сначала мы потеряем массив, который сообщает нам, каковы другие наши указатели. Этот фрагмент или память будут возвращены системе, и поэтому их нельзя будет надежно прочитать.

  int a=0;
  int b=1;
  int c=2;

  ppArr = new int *[3];

  ppArr[0] = &a;
  ppArr[1] = &b;
  ppArr[2] = &c;

Об этом, думаю, тоже стоит упомянуть. Тот факт, что вы работаете с указателями, не означает, что память, на которую указывают указатели, была выделена динамически. Другими словами, наличие указателя не означает, что его необходимо удалить. Массив, который я создал здесь, выделяется динамически, но указатели указывают на локальные экземпляры целых чисел. Когда мы удаляем его, нам нужно только удалить массив.

  delete [] ppArr;

  return 0;

}

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

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

Приятно, я не знал об этом!

Frank 29.09.2010 18:14

Я не знаю, почему на этот вопрос ответили так запутанно долго.

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

Вы удалили кучу адресов, но ни одного объекта.

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

Плевать, что он просто удалил кучу адресов объектов, он просто видит целые числа.

Вот почему вам нужно сначала просмотреть массив! и вызовите удаление для каждого элемента, тогда вы можете удалить хранилище самого массива.

Что ж, теперь ответ мой получился довольно длинным ... .... странно ...;)

Редактировать: Ответ Джейсона не является неправильным, он просто не подходит. Ни один компилятор, ни что-либо еще в c (++) не заботится о том, чтобы вы удаляли вещи, которые находятся в другом месте указал на. Ты просто можешь это сделать. Другие части программы пытаются использовать удаленные объекты будет нарушать ваши правила. Но никто вам не помешает. Также не будет проблемой уничтожить массив указателей на объекты, когда объекты упоминаются в другом месте.

«Другие части программы, пытающиеся использовать удаленные объекты, будут отказываться от вас» .... segfaulting, вероятно, лучший возможный результат, он ловит место, где находится проблема. Но есть много других возможностей, которые не будут замечены позже и могут даже вызвать повреждение, продолжающееся после выхода из программы (например, если буфер записи файла был выделен в теперь свободной памяти).

Ben Voigt 15.02.2010 05:38

Возьмем (псевдокодированный) реальный пример. Представьте, что у вас есть такой класс:

class Street
{
    public:
        Street();
        ~Street();
    private:
        int HouseNumbers_[];
}

typedef *Street StreetSign;

Если у вас есть массив уличных знаков, и вы удаляете свой массив уличных знаков, это не означает, что вы автоматически удаляете их. Они все еще там, кирпичи и строительный раствор, просто на них больше нет указателей. Вы избавились от экземпляров эти конкретные указателей на улицы.

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

Если вы удаляете [] массив указателей, все, что вам нужно сделать, это удалить массив целых чисел.

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