[英]How to delete void pointer?
在 C++ 中删除这样的对象有什么问题吗?
MyCls* c = new MyCls();
void* p = (void*)c;
delete (MyCls*)p;
这书面是合法的。
回到MyCls*
至关重要。 否则,您将调用未定义的行为——将不会调用 MyCls 析构函数,并且还可能出现其他问题(例如崩溃)。 您必须转换回正确的类型。
另请注意,如果涉及多重继承并使用多重转换,这可能会很复杂。 您的演员必须在任一方向“匹配”。
如果您的代码结构使得您在销毁时不知道类型,请为每个可删除对象提供一个带有虚拟析构函数的公共基类。 然后在调用 delete 之前转换回基类。
代码定义明确。 两种类型转换都是静态类型转换,尽管使这种类型显式( static_cast<void*>
等)而不是使用 C 样式类型转换是一种很好的风格。 该标准表示,如果指向对象的指针被转换为空指针并通过静态转换返回,它将保持其原始值。 因此,您的最终delete
表达式应具有与delete c
相同的效果。
话虽如此,使用void*
通常是 C++ 中的代码异味。
删除后将指针设置为nullptr
是一个好习惯,尤其是为了避免在另一个线程/事件处理程序中访问冲突/段错误。
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
s 和delete
s。 尝试强制执行只有构造函数可以调用new
并且只有析构函数可以调用delete
的规则,这将有助于您更好地组织代码。
如果您使用的是 C++11,请始终尝试std::shared_ptr
等,这将自动为您执行上述操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.