До delete b;
все в порядке. Следующая строка (a->setRadius(4.0);
) вызовет неопределенное поведение, поскольку вы обращаетесь к удаленному объекту. Проблема в том, что в 90% случаев он будет работать (да, это проблема, потому что в остальных 10% случаев он будет падать, и вы потеряете ночь, выясняя причину!)
Почему это? Это происходит потому, что многие реализации операторов new и delete не «запрашивают» память у ОС при каждом вызове. Они просят большой блок этого и затем используют это немного за один раз. Когда вы удаляете свой объект, память только «помечается» как свободная и не освобождается. Поэтому, когда вы обращаетесь к освобожденному объекту, вы обращаетесь к памяти, которая (вероятно) все еще выделена вашему процессу, но которую вы не должны использовать. В середине какая-то другая часть вашей программы могла бы выделить ее и изменить, или просто оператор удаления мог увидеть, что там было так много памяти, «помеченной как свободная», и решил вернуть ее в ОС, вызывая SEGFAULT, если вы попробуйте получить к нему доступ. «Отладочная» версия удаления может заполнить его шаблоном или обнулить его, так что если вы посмотрите его, станет более очевидным, что он используется или свободен ... Есть много вариантов.
Примечание: я упростила обработку памяти новыми и удаляемыми. «Обычно» есть еще несколько уровней косвенности. Но они не имеют отношения к обсуждению.
В некоторых реализациях new / delete / malloc / free при отладке строит память, вместо обнуления, заполняется 0xcc или 0xcdcd. Это по двум причинам. Если я правильно помню, во-первых, 0xcc - это инструкция Intel для точки останова INT 3 (а 0xcdcd - это кратное число или что-то подобное). Другая причина в том, что если вы смотрите его в отладчике, шаблон будет совершенно очевиден, в то время как шаблон «все 0x00» будет сложнее различить.