Подтвердить что ты не робот

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

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

delete [] PointerToPointers;

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

  delete pI;
  delete [] pArr;

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

  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;

Это, я думаю, следует упомянуть. Просто потому, что вы работаете с указателями, это не означает, что память, на которую указывают эти указатели, была динамически распределена. То есть только потому, что у вас есть указатель, это не значит, что его обязательно нужно удалить. Созданный мной массив динамически выделяется, но указатели указывают на локальные экземпляры int. Когда мы удаляем это, нам нужно только удалить массив.

  delete [] ppArr;

  return 0;

}

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

Ответ 3

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

Ответ 4

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

Ответ 5

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

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

typedef *Street StreetSign;

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

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

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

Ответ 6

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

Ответ 7

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

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

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

delete не заботится о содержимом пространства памяти, он вызывает деструктор и маркирует mem как свободный.

Не важно, что он просто удалил кучу адресов объектов, он просто видит ints.

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

Ну, теперь мой ответ немного длинный...... странный...;)

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