первый вопрос: можно и нужно ли после этого вызывать delete, чтобы передать очищенную память в пользование ОС?
Если ты заглянешь в стандарт С++, в место определяющее
оператор delete, то увидишь, что его можно вызывать только для памяти выделенной new. Поскольку память под код функций ты не выделял через new, то и delete вызывать нельзя.
Что будет, если создать что-то вроде продвинутого singleton, который будет динамически выделять память для класса при запуске, а после выполнения функций можно будет вызвать функцию, которая просто сотрёт класс и отпустит память?
В принципе это можно реализовать. Но приведённая реализация даже близко не делает того, что ты ожидаешь.
Сначала может показаться, что она работает. Память, правда, возвращаться в ОС не будет. Потом ты может быть заметишь, что код тоже остаётся на месте. Потом ты может быть заметишь, что программа иногда падает из-за NULL-пойнтера в каком-то другом объекте. Короче, если ты сможешь это отладить, у тебя прибавится знаний в том, как всё устроено на уровне ассемблера. Если не сможешь, то твою программу ждут чудесные падения, а тебя -- не менее чудесные баг-репорты.