Все уже говорили вам, что вы не должны этого делать и что это приведет к неопределенному поведению. Это широко известно, поэтому давайте уточним это на более низком уровне и посмотрим, что на самом деле происходит.
Стандартный универсальный ответ: все может случиться, это не совсем так. Например, компьютер не будет пытаться убить вас за это (если вы не программируете AI для робота):)
Причина, по которой не может быть универсального ответа, заключается в том, что, поскольку он не определен, он может отличаться в разных компиляторах и даже в разных версиях одного и того же компилятора.
Но вот что "грубо" происходит в большинстве случаев:
delete
состоит из 2 основных операций:
- вызывает деструктор, если он определен
- это как-то освобождает память, выделенную для объекта
Таким образом, если ваш деструктор содержит какой-либо код, который обращается к любым данным класса, который уже был удален, это может привести к ошибке или, скорее всего, к прочтению некоторых бессмысленных данных. Если эти удаленные данные являются указателями, то, скорее всего, это будет ошибка по умолчанию, поскольку вы попытаетесь получить доступ к памяти, которая содержит что-то другое или не принадлежит вам.
Если ваш конструктор не касается каких-либо данных или не присутствует (давайте не будем рассматривать здесь виртуальные деструкторы для простоты), это может не быть причиной сбоя в большинстве реализаций компилятора. Однако вызов деструктора - не единственная операция, которая должна произойти здесь.
Память должна быть свободна. Как это сделать, зависит от реализации в компиляторе, но он может также выполнять некоторую free
подобную функцию, давая ей указатель и размер вашего объекта. Вызов free
для уже удаленной памяти может привести к сбою, поскольку память может больше не принадлежать вам. Если он принадлежит вам, он может не сразу аварийно завершить работу, но он может перезаписать память, которая уже была выделена для какого-либо другого объекта вашей программы.
Это означает, что одна или несколько ваших структур памяти только что были повреждены, и ваша программа, скорее всего, рано или поздно вылетит или может вести себя невероятно странно. Причины не будут очевидны в вашем отладчике, и вы можете потратить недели на выяснение того, что, черт возьми, только что произошло.
Итак, как уже говорили другие, это вообще плохая идея, но я полагаю, вы уже это знаете. Не беспокойтесь, невинный котенок, скорее всего, не умрет, если вы дважды удалите объект.
Вот пример кода, который является неправильным, но может также хорошо работать (он работает нормально с GCC на Linux):
class a {};
int main()
{
a *test = new a();
delete test;
a *test2 = new a();
delete test;
return 0;
}
Если я не создаю промежуточный экземпляр этого класса между удалениями, 2 обращения к свободным в той же памяти происходят, как и ожидалось:
*** Error in `./a.out': double free or corruption (fasttop): 0x000000000111a010 ***
Чтобы ответить на ваши вопросы напрямую:
Что может случиться худшее :
Теоретически ваша программа вызывает что-то фатальное. В некоторых крайних случаях он может даже попытаться стереть ваш жесткий диск. Вероятность зависит от того, что на самом деле представляет ваша программа (драйвер ядра? Программа пространства пользователя?).
На практике, скорее всего, это просто сбой с segfault. Но может случиться что-то худшее.
Будет ли компилятор выдавать ошибку ?
Не должно.