Удалить элемент указателя типа массива ошибка? - PullRequest
1 голос
/ 25 марта 2020

У меня есть пример:

int* arr = new int[1];
//First Time
arr[0] = 5;
cout << &arr[0] << " " << arr[0] << endl;
delete &arr[0];
cout << &arr[0] << " " << arr[0] << endl;

//Second time
arr[0] = 5;
cout << &arr[0] << " " << arr[0] << endl;
delete &arr[0]; //Error from here
cout << &arr[0] << " " << arr[0] << endl;

Результат из кода выше:

00529EF0 5
00529EF0 -572662307
00529EF0 5
//Where the code stop

Я не знаю, почему это вызывает у меня ошибку? Он не позволяет мне удалить arr[0] во второй раз, даже если первый раз успешно удален, и я назначаю ему новое значение.

Ответы [ 2 ]

4 голосов
/ 25 марта 2020

Если вы динамически выделяете массив с помощью new[], вы должны удалить его с помощью delete[], что освободит весь массив. Вы не можете освободить отдельные элементы. Ваш код имеет неопределенное поведение, потому что вы использовали delete вместо delete[], так что может произойти все что угодно. То, что это сработало, не означает, что это правильно.

1 голос
/ 25 марта 2020

Неопределенное поведение .

&arr[0] - это тот же адрес памяти, на который arr распадается . Значит, вы действительно звоните delete arr;. Это неопределенное поведение , потому что вы используете delete, когда вам нужно использовать delete[]. Память, выделенная с помощью new ДОЛЖНА , должна быть освобождена с помощью delete. Память, выделенная с помощью new[] ДОЛЖНА , должна быть освобождена с помощью delete[].

Но, давайте предположим, во время выполнения вашего компилятора достаточно информации в метаданных выделенного массива, чтобы освободить массив правильно. delete При массиве освобождается весь массив. Вы не можете освободить отдельные элементы массива. И доступ к любому элементу массива после освобождения всего массива - это неопределенное поведение . Вы обращаетесь к arr[0] после вызова delete arr; для освобождения массива. Вы не выделяете новый массив для arr, на который нужно указать. Вам повезло, что ваш код не просто взломал sh сразу.

Это определение неопределенного поведения - НИЧЕГО может произойти. Вы можете прочитать старую память, прежде чем она будет перезаписана. Вы могли читать из случайной памяти. Вы можете испортить память. Вы могли бы взломать sh.

...