Подтвердить что ты не робот

Как удалить указатель void?

Есть ли что-то неправильное при удалении такого объекта в С++?

MyCls* c = new MyCls();
void* p = (void*)c;
delete (MyCls*)p;
4b9b3361

Ответ 1

Это, как написано, является законным.

Возврат к MyCls* имеет решающее значение. Без этого вы вызовете поведение undefined - деструктор MyCls не будет вызван, и могут возникнуть другие проблемы (например, сбой). Вы должны вернуть правильный тип.

Также обратите внимание, что это может быть сложно, если задействовано множественное наследование и используются несколько приведений. Ваши броски должны "совпадать" в любом направлении.

Если ваш код структурирован таким образом, что вы не будете знать тип во время уничтожения, дайте каждому удаляемому объекту общий базовый класс с виртуальным деструктором. Затем вернитесь к базовому классу до того, как вызывается delete.

Ответ 2

Код четко определен. Оба броска - это статические ролики, хотя хороший стиль позволяет сделать это явным (static_cast<void*> и т.д.) Вместо использования стилей C-стиля. В стандарте говорится, что если указатель на объект преобразуется в указатель void и обратно статическими кастами, он сохранит свое первоначальное значение. Таким образом, ваше окончательное выражение delete должно иметь тот же эффект, что и delete c.

При этом использование void* часто является запахом кода в С++.

Ответ 3

Рекомендуется устанавливать указатели на 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* не вызовет деструктор, и это может привести к утечке памяти или другим проблемам.

Ответ 4

Хотя этот код действителен, это не очень хорошая практика.

В качестве общего руководства не должно быть new и delete в дикой природе. Попробуйте применить правило, которое только конструкторы могут вызвать new, и только деструкторы могут вызвать delete, поможет вам лучше упорядочить код.

Если вы используете С++ 11, всегда попробуйте std::shared_ptr и тому подобное, это автоматически сделает это за вас.