Непонятно о `delete` и указателях - PullRequest
1 голос
/ 30 июня 2010

Скажем, у нас есть кусок кода:

//...
class A
//...
A* myA = new A();
A* myPointerToMyA = myA;
delete myA;
delete myPointerToMyA; // this is wrong, no?
//...

Последняя строка делает то же самое, что и над ней, правильно?Так что теперь я буду delete указывать недействительный / NULL-указатель?

Я понимаю, что это может быть глупым вопросом, но все же мне нужно некоторое подтверждение.

Ответы [ 6 ]

5 голосов
/ 30 июня 2010

Да, это неправильно. Когда вы используете delete, вы не удаляете указатель. Скорее вы удаляете то, на что он указывает. Таким образом, когда вы используете delete on указатель, память, на которую указывает этот указатель, освобождается. Любой другой указатель, который указывает на эту память, теперь указывает на нераспределенную память и является висящим указателем . Использование висячего указателя приводит к неопределенному поведению, и, конечно, недопустимо пытаться освободить уже освобожденную память, поэтому использование delete для висящего указателя определенно неверно. Это может привести к ошибке сегментации.

5 голосов
/ 30 июня 2010

Действительно, это неправильно.И в отличие от одного из других комментариев, это не потому, что вы не наделили его новым.

И myA, и myPointerToMyA указывают на одно и то же.Удаление через любой из них - это нормально, но вы можете удалить его только один раз, потому что они указывают на одно и то же - удаляется именно то, на что указывает, а не сам указатель.

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

В этом случае удаление указателя на удаленный объект,поведение «неопределено» - среда выполнения может делать то, что ему нравится!(Я могу гарантировать, что вам это не понравится ...)

1 голос
/ 30 июня 2010

Здесь вы получите следующее:

A* myA = new A();          // myA is now equal to 0x11110000 for example(!)
A* myPointerToMyA = myA;   // myPointerToMyA is now equal to 0x11110000
delete myA;                // equal to delete (A*)(0x11110000)
delete myPointerToMyA;     // equal to delete (A*)(0x11110000)

Две последние строки в конце равны. Этот код приведет к неопределенному поведению.

1 голос
/ 30 июня 2010

Вы правы.

Итак, я хотел бы удалить недействительный указатель / NULL?

Технически, это только недействительно, потому что ничего не было установлено на NULL. Все в порядке с delete NULL указателем .

0 голосов
/ 30 июня 2010

2 указателя указывают на один и тот же объект.Объект разрушается после первого вызова delete myA;.При повторном вызове delete (delete myPointerToMyA;) вы пытаетесь удалить объект более одного раза, и результат такого действия не определен (обычно вы получаете исключение времени выполнения).

0 голосов
/ 30 июня 2010

Да, это неправильно.Память, выделенная для new A() и освобожденная delete myA.Следует отметить, что хотя delete myPointerToMyA является попыткой удалить недопустимый указатель, это не попытка удалить нулевой указатель, поскольку myPointerToMyA не равно NULL.

...