如何删除void指针?

时间:2014-07-16 05:18:17

标签: c++ pointers void delete-operator

在C ++中删除这样的对象时有什么问题吗?

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

4 个答案:

答案 0 :(得分:68)

这是合法的。

回归MyCls*至关重要。如果没有它,您将调用未定义的行为 - 不会调用MyCls析构函数,也可能出现其他问题(例如崩溃)。你必须回到正确的类型。

另请注意,如果涉及多个继承并使用多个强制转换,则此操作可能会很复杂。你的演员必须"匹配"在任何一个方向。

如果您的代码的结构使得您在销毁时不知道类型,请为每个可删除对象提供一个带有虚拟析构函数的公共基类。然后在调用delete之前强制转换回基类。

答案 1 :(得分:29)

代码定义明确。两个强制转换都是静态强制转换,尽管使用C风格的强制转换(static_cast<void*>等。)是一种很好的风格。标准说如果指向对象的指针转换为void指针并由静态转换返回,它将保持其原始值。因此,您的最终delete表达式与delete c具有相同的效果。

话虽如此,使用void*通常是C ++中的代码味道。

答案 2 :(得分:0)

虽然这段代码有效,但这不是一个好习惯。

作为一般准则,不应该有newdelete 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*不会调用析构函数,这可能导致内存泄漏或其他问题。