在C ++中删除这样的对象时有什么问题吗?
MyCls* c = new MyCls();
void* p = (void*)c;
delete (MyCls*)p;
答案 0 :(得分:68)
这是合法的。
回归MyCls*
至关重要。如果没有它,您将调用未定义的行为 - 不会调用MyCls析构函数,也可能出现其他问题(例如崩溃)。你必须回到正确的类型。
另请注意,如果涉及多个继承并使用多个强制转换,则此操作可能会很复杂。你的演员必须"匹配"在任何一个方向。
如果您的代码的结构使得您在销毁时不知道类型,请为每个可删除对象提供一个带有虚拟析构函数的公共基类。然后在调用delete之前强制转换回基类。
答案 1 :(得分:29)
代码定义明确。两个强制转换都是静态强制转换,尽管使用C风格的强制转换(static_cast<void*>
,等。)是一种很好的风格。标准说如果指向对象的指针转换为void指针并由静态转换返回,它将保持其原始值。因此,您的最终delete
表达式与delete c
具有相同的效果。
话虽如此,使用void*
通常是C ++中的代码味道。
答案 2 :(得分:0)
虽然这段代码有效,但这不是一个好习惯。
作为一般准则,不应该有new
和delete
s。尝试强制执行只有构造函数可以调用new
的规则,只有析构函数可以调用delete
来帮助您更好地组织代码。
如果您使用的是C ++ 11,请始终尝试std::shared_ptr
等,这将自动为您执行上述操作。
答案 3 :(得分:0)
删除后将指针设置为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*
不会调用析构函数,这可能导致内存泄漏或其他问题。