Я столкнулся со своим первым компилятором, который изменяется, lvalue передал:: удалите, но не обнуляйте lvalue. Это следующее, верно:
Foo * p = new Foo();
Foo * q = p;
assert(p != 0);
assert(p == q);
::delete p;
assert(p != q);
assert(p != 0);
Обратите внимание, что p не является нулем после удалить операции, и это изменилось от, он - старое значение. Коллега сказал мне, что это весьма обычно, по его опыту, работавший с некоторыми мейнфреймовыми компиляторами C++, которые изменили бы p на 0xFFFFFFFF, а также другие компиляторы, которые изменят p на 0.
Где в Стандарте C++ это говорит, что компилятору позволяют сделать это?
Перерывая StackOverflow, я нашел этот вопрос: Почему не удаляет, устанавливает указатель в NULL? который имел ответ, который упомянул ответ Bjarne Stroustrup, который включает оператор:
C++ явно позволяет реализацию, удаляют для обнуления lvalue операнда, и я надеялся, что реализации сделают это, но та идея, кажется, не стала популярной у реализаторов.
Я считал и перечитал раздел 5.3.5, и 12.5 из заключительного комитета проектируют C++ 0x стандарт, но я не вижу "явную" часть. Я просто смотрю в неправильных разделах стандарта? Или есть ли цепочка логики, которая находится в разделах, но я просто не соединяюсь вместе правильно.
У меня нет своей копии Аннотируемого Справочника C++ больше. Это было в ARM, что компилятор мог сделать это?
[Редактирование: Исправление ссылки раздела от 3.5.3 до 5.3.5. Я также добавляю интересный парадокс как контрапункт к утверждению Henk, что p не определен после того, как удаляют.]
Существует интересный парадокс, если p инициализируется к пустому указателю.
Foo * p = 0;
Foo * q = p;
assert(p == 0);
assert(p == q);
::delete p;
assert(p == q);
assert(p == 0);
В этом случае, хотя, поведение хорошо документируется. То, когда удаляют, получает нулевого указателя, это, предполагают, чтобы ничего не сделать, таким образом, p остается неизменным.
Возможно, это не так явно. В 5.3.5 / 7 говорится, что выражение удаления вызовет функцию освобождения памяти. Затем в 3.7.3.2/4 говорится, что использование освобожденного указателя не определено. Поскольку значение указателя нельзя использовать после освобождения, то, сохраняет ли указатель значение или значение изменяется реализацией, не имеет значения.
5.3.5/7
Выражение удаления вызовет функцию освобождения (3.7.3.2).
3.7.3.2/4
Если аргумент, переданный функции освобождения в стандартной библиотеке, является указателем, который не является значением нулевого указателя (4.10), функция освобождения освобождает память, на которую ссылается указатель, render - сделать недействительными все указатели, относящиеся к любой части освобожденного хранилища. Эффект от использования недопустимого значения указателя (включая передачу его в функцию освобождения) не определен .
Ссылки взяты из действующего стандарта. В готовящемся к выпуску стандарте 5.3.5 / 7 была изменена формулировка:
C ++ 0x FD 5.3.5 / 7
Если значение операнда выражения удаления не является значением нулевого указателя, удаление- выражение вызовет функцию освобождения (3.7.4.2). В противном случае не указано, будет ли вызываться функция освобождения. [Примечание: функция освобождения вызывается независимо от того, генерирует ли деструктор для объекта или какого-либо элемента массива исключение. - конец примечания]