Как удаление в C ++ знает, сколько областей памяти для удаления - PullRequest
5 голосов
/ 24 февраля 2010

как работает оператор удаления? Это лучше, чем бесплатно ()? Также, если вы делаете ptr=new char[10], то удаляете, используя delete ptr, как указатель узнает, сколько мест удалить

Ответы [ 7 ]

16 голосов
/ 24 февраля 2010

Существует только оператор delete, free существует только как функция. В C ++ рекомендуется использовать new / delete более malloc() / free().


В операторе удаления есть внутренняя "магия". Когда массив создается с new[], размер массива сохраняется в метаданных в блоке памяти. delete[] использует эту информацию.

Все это, конечно, зависит от компилятора, ОС, оптимизатора и реализации.

5 голосов
/ 24 февраля 2010

, если вы делаете не массив типа:

T t = new T;
// ...
delete t;

Он будет знать, сколько нужно удалить, потому что он знает, какой большой T. Если вы делаете массив:

T t* = new T[10];
// ...
delete [] t;

Он установит некоторую дополнительную информацию с распределением, чтобы указать, сколько нужно удалить. Обратите внимание, мы используем delete [] t с дополнительными [], чтобы сказать, что это массив. Если вы этого не сделаете, он подумает, что это просто T и освободит только столько памяти.

Всегда используйте delete, если вы используете new и free, если вы используете malloc. new сначала делает 2 вещи, выделяет память, затем создает объект. Точно так же delete вызывает деструктор и затем освобождает память. malloc\free имеет дело только с выделением и освобождением памяти.

3 голосов
/ 24 февраля 2010

Конкретно отвечая на ваш вопрос, оператор delete вызывает деструктор, а free - нет; следовательно, причина, по которой вы не хотите смешивать malloc / free с new / delete.

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

Скажем, вы malloc 128 байтов или новый массив из восьми 16-байтовых объектов. Компилятор может фактически захватить 256 байтов, включить небольшой блок управления кучей в начале, записать, что он дал вам 128, но захватил 256, и вернуть вам смещение в этот блок 256 где-то после его заголовка. Вам гарантировано, что из этого указателя у вас есть 128 байтов, которые вы можете использовать, но если вы выйдете за пределы этого, у вас могут возникнуть проблемы.

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

3 голосов
/ 24 февраля 2010

Это не вопрос лучше или хуже. Оба являются операциями с одной и той же целью, распределением и освобождением памяти, но обычно они используются в другом контексте C и C ++. Кроме того, между двумя наборами операций есть некоторые важные различия:

  • new / delete являются ключевыми словами C ++ и недоступны на языке C
  • new / delete являются типобезопасными, тогда как malloc() / free() - нет. Это означает, что указатели, возвращаемые malloc() и free(), являются void указателями, которые необходимо привести к правильному типу.
  • new / delete неявно поддерживают выделение и удаление массива с использованием синтаксиса new[] и delete[] с использованием метаданных, предоставленных компилятором, malloc() / free() не поддерживают этот синтаксис
  • применение new / delete к типу класса T вызовет конструктор и деструктор соответственно T, malloc() / free(), не вызовет конструктор и деструктор T
  • malloc() вернет NULL в случае исчерпания памяти, new сгенерирует исключение

Обратите внимание, что для предотвращения повреждения памяти, выделенная с помощью new память должна быть освобождена с помощью delete. То же самое касается памяти, выделенной с помощью malloc(), которая должна быть освобождена с помощью free().

3 голосов
/ 24 февраля 2010

Реализация определяет количество уничтожаемых элементов (при использовании delete []) для вас. Например:

  • new char [10] может выделить несколько дополнительных байтов, поместить количество элементов в начало, а затем вернуть указатель на первый элемент. delete [] может затем посмотреть за указателем на сохраненный счетчик
  • хранит эквивалент std :: map и new T [n] создаст ключ с возвращенным указателем и значение с количеством. delete [] будет искать указатель на этой карте
  • что-то совершенно другое. Для вас не имеет значения, как это делается, просто то, что это делается (и, как указали другие ответы, используйте delete [] с новым [] !!)
3 голосов
/ 24 февраля 2010
  1. В C ++ конструктор вызывается с использованием new, но не при использовании malloc. Аналогичным образом деструктор вызывается при использовании delete, но не при использовании free.

  2. Если вы заново создали массив, используя MyClass * x = new MyClass [25], вам нужно вызвать delete [] x, чтобы система знала, что он удаляет (и уничтожает) группу объекты вместо одного.

2 голосов
/ 24 февраля 2010

Добавление к ответу @ Vlad, если вы выделяете память, используя новую [] форму оператора, например:

char *c = new char[10];

, тогда вы должны использовать соответствующую форму для удаления:

delete[] c;

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

[EDIT]

Почему вы не можете использовать символ c []

Поскольку компилятору нужно знать размер, который он должен выделить для переменной c во время компиляции. Однако использование новой формы [] говорит ей отложить выделение до времени выполнения. Следовательно, ошибка компилятора.

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