Я думаю, что неявный вопрос заключался в том, что вы не можете удалить с помощью void*
, поэтому кажется странным, что вы можете удалить с помощью shared_ptr<void>
.
Вы не можете удалить объект с помощью необработанного void*
главным образом потому, что он не знает, какой деструктор вызвать. Использование виртуального деструктора не помогает, потому что void
не имеет vtable (и, следовательно, виртуального деструктора).
Джеймс МакНеллис четко объяснил, почему shared_ptr<void>
работает, но здесь есть кое-что интересное: Предполагая, что вы следуете документированной лучшей практике , чтобы всегда использовать следующую форму при вызове new
...
shared_ptr<T> p(new Y);
... при использовании shared_ptr необязательно иметь виртуальный деструктор. Это верно, если T равно void
, или в более знакомом случае, когда T представляет собой полиморфную основу Y .
Это идет вразрез с давним общепринятым мнением: Что интерфейсные классы ДОЛЖНЫ иметь виртуальных деструкторов.
Проблема OP delete (void*)
решается тем фактом, что конструктор shared_ptr является шаблоном, который запоминает тип данных, который требуется для уничтожения . Этот механизм решает проблему виртуального деструктора точно таким же образом.
Таким образом, даже если фактический тип объекта не обязательно фиксируется в типе самого shared_ptr (поскольку T не обязательно должен быть того же типа, что и Y ), тем не менее, shared_ptr запоминает, какой тип объекта он держит, и выполняет приведение к этому типу (или делает что-то эквивалентное этому), когда приходит время удалить объект.