В ответе qaru.site/info/9629/... есть цитата из Stroustrup:
С++ явно позволяет реализовать удаление, чтобы обнулить lvalue operand, и я надеялся, что реализация этого сделает, но эта идея, похоже, не стала популярной среди разработчиков.
Однако я не смог найти этот явный оператор в стандарте. Существует часть текущего проекта стандарта (N4659), который можно интерпретировать следующим образом:
6.7
Когда достигнут конец продолжительности области хранения, значения всех указателей, представляющих адрес любой части этого область хранения становится недопустимой величиной указателя (6.9.2). косвенность через недопустимое значение указателя и передачу недопустимого значения указателя к функции дезадаптации не удалось определить поведение. Любое другое использование неверное значение указателя имеет поведение, определяемое реализацией.
Сноска: некоторые реализации могут определять, что копирование недопустимого значения указателя вызывает системную ошибку выполнения
Итак, после значения delete ptr;
, ptr
становится недопустимым значением указателя, и использование этого значения имеет поведение, определенное реализацией. Тем не менее, он не говорит, что значение ptr
разрешено изменять.
Это может быть философский вопрос, как можно решить, изменилось ли значение, если нельзя использовать его значение?
6,9
Для любого объекта (кроме подобъекта базового класса) тривиально тип копирования T, независимо от того, имеет ли объект допустимое значение типа T, базовые байты (4.4), составляющие объект, могут быть скопированы в массив из char, unsigned char или std:: byte (21.2.1).43 Если содержимое этого массива копируется обратно в объект, объект должен впоследствии сохраняют свое первоначальное значение.
Итак, похоже, что значение memcpy
недопустимо для указателя в массив char (в зависимости от того, какой оператор "сильнее", 6.7 или 6.9). Для меня 6.9 кажется более сильным).
Таким образом, я могу обнаружить, что значение указателя было изменено на delete
: memcpy
значение указателя до и после массива delete
до char, а затем сравнить их.
Итак, как я понимаю, 6.7 не гарантирует, что delete
разрешено изменять его параметр.
Разрешено ли разрешению изменять его параметр?
Ознакомьтесь с комментариями здесь: qaru.site/info/166494/...
Здесь маловероятный, но все же возможный код реального мира, где это имеет значение:
SomeObject *o = ...; // We have a SomeObject
// This SomeObject is registered into someHashtable, with its memory address
// The hashtable interface is C-like, it handles opaque keys (variable length unsigned char arrays)
delete o;
unsigned char key[sizeof(o)];
memcpy(key, &o, sizeof(o)); // Is this line OK? Is its behavior implementation defined?
someHashtable.remove(key, sizeof(key)); // Remove o from the hashtable
Конечно, этот фрагмент может быть переупорядочен, поэтому он становится достоверным кодом. Но вопрос в том, что это действительный код?
Вот связанный ход мысли: предположим, что реализация определяет, что описывает сноска:
копирование недопустимого значения указателя вызывает системную ошибку выполнения
6.9 гарантирует, что я могу memcpy()
любое значение. Даже недействительный. Таким образом, в этой теоретической реализации, когда я memcpy()
значение недопустимого указателя (что должно быть успешным, 6.9 гарантирует это), в некотором смысле я не использую недопустимое значение указателя, а только его базовые байты (потому что он будет генерировать runtime fault и 6.9 не позволяет), , поэтому 6.7 не применяется.