Работает ли оператор delete [] с динамически выделяемой памятью, возвращаемой через указатель? - PullRequest
4 голосов
/ 22 сентября 2011

Мне интересно, как операторы delete [] работают с указателями , возвращаемыми функцией , вместо того, чтобы иметь динамическое размещение в той же области, что и оператор delete.Допустим, у меня есть такая тривиальная функция:

int *getArray()
{
    int *returnVal = new int[3];
    returnVal[0] = returnVal[1] = returnVal[2] = 0;
    return returnVal;
}

Теперь, когда мне нужно использовать этот массив в моем коде, я буду делать следующее:

int *vals = getArray();
// use values...
delete[] vals;

Однако яМне интересно, как компилятор C ++ узнает, насколько большим был выделен блок памяти (и, следовательно, сколько элементов памяти нужно удалить из vals)?Это правильный метод, или мне нужно было бы удалять каждое значение массива отдельно (как в коде ниже)?

int *vals = getArray();
// use values...
delete vals + 2;
delete vals + 1;
delete vals;

Ответы [ 4 ]

4 голосов
/ 22 сентября 2011

Вы должны только delete[] вещи, полученные через new[]. В вашем коде это значение, возвращаемое getArray(). Удаление чего-либо еще является незаконным.

Однако мне интересно, как компилятор C ++ знает, насколько велика выделенный блок памяти был

Каждая реализация каким-то образом сохраняет выделенный размер (и тип, который я думаю).

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

Конечно, это слишком просто объясняется (это больше похоже на объяснение C). В C ++ добавлены детали деструкторов и еще много чего.

2 голосов
/ 22 сентября 2011

Краткий ответ: это работает.

Фактически, единственное действительное, что можно сделать с указателем, полученным из new[], это delete[] it.

Компилятор вставит дополнительныеинформация в память, которую она получает от ОС, чтобы позволить ей отслеживать, насколько велики выделенные блоки.Эта информация позволяет правильно уничтожать и освобождать данные, которые идентифицируются только указателем.

2 голосов
/ 22 сентября 2011

Можно полностью удалить память из новой области видимости []. Подробнее здесь и вот цитата, если вам лень проверять ссылку.

[16.14] После того, как p = new Fred [n], как компилятор узнает, что при удалении будет уничтожено n объектов [] p?

Краткий ответ: Магия.

Длинный ответ: система времени выполнения хранит количество объектов, n, где его можно найти, если вы знаете только указатель, с. Есть два популярных метода, которые делают это. Обе эти техники используются компиляторами коммерческого уровня, у обоих есть компромиссы, и ни один не совершенен. Эти методы:

  1. Перераспределить массив и поставить n слева от первого объекта Fred.
  2. Используйте ассоциативный массив с p в качестве ключа и n в качестве значения.
0 голосов
/ 22 сентября 2011

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

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