Есть ли что-то неправильное при удалении такого объекта в С++?
MyCls* c = new MyCls();
void* p = (void*)c;
delete (MyCls*)p;
Есть ли что-то неправильное при удалении такого объекта в С++?
MyCls* c = new MyCls();
void* p = (void*)c;
delete (MyCls*)p;
Это, как написано, является законным.
Возврат к MyCls*
имеет решающее значение. Без этого вы вызовете поведение undefined - деструктор MyCls не будет вызван, и могут возникнуть другие проблемы (например, сбой). Вы должны вернуть правильный тип.
Также обратите внимание, что это может быть сложно, если задействовано множественное наследование и используются несколько приведений. Ваши броски должны "совпадать" в любом направлении.
Если ваш код структурирован таким образом, что вы не будете знать тип во время уничтожения, дайте каждому удаляемому объекту общий базовый класс с виртуальным деструктором. Затем вернитесь к базовому классу до того, как вызывается delete.
Код четко определен. Оба броска - это статические ролики, хотя хороший стиль позволяет сделать это явным (static_cast<void*>
и т.д.) Вместо использования стилей C-стиля. В стандарте говорится, что если указатель на объект преобразуется в указатель void и обратно статическими кастами, он сохранит свое первоначальное значение. Таким образом, ваше окончательное выражение delete
должно иметь тот же эффект, что и delete c
.
При этом использование void*
часто является запахом кода в С++.
Рекомендуется устанавливать указатели на nullptr
после удаления, особенно во избежание нарушения прав доступа /segfault в другом потоке/обработчике событий.
auto c = new MyCls();
auto p = static_cast<void*>c;
delete static_cast<MyCls*>p;
p = nullptr;
c = nullptr;
Еще лучше использовать умные указатели и вообще избегать new
/delete
.
{
auto c = std::make_unique<MyCls>();
auto p = static_cast<void*>(c.get());
// no need to delete p
} // c will be released automatically during unwinding
В C++ предпочтительны явные приведения, такие как static_cast
.
Если ~MyCls()
нетривиален, он будет вызван, потому что вы разыгрываете p
в MyCls*
. Удаление void*
не вызовет деструктор, и это может привести к утечке памяти или другим проблемам.
Хотя этот код действителен, это не очень хорошая практика.
В качестве общего руководства не должно быть new
и delete
в дикой природе. Попробуйте применить правило, которое только конструкторы могут вызвать new
, и только деструкторы могут вызвать delete
, поможет вам лучше упорядочить код.
Если вы используете С++ 11, всегда попробуйте std::shared_ptr
и тому подобное, это автоматически сделает это за вас.