简体   繁体   English

如何删除空指针?

[英]How to delete void pointer?

Is there anything wrong when deleting an object like this in C++?在 C++ 中删除这样的对象有什么问题吗?

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

This as written is legal.这书面是合法的。

The cast back to MyCls* is critical.回到MyCls*至关重要。 Without that, you will invoke undefined behavior--the MyCls destructor will not be called, and other problems may arise as well (such as a crash).否则,您将调用未定义的行为——将不会调用 MyCls 析构函数,并且还可能出现其他问题(例如崩溃)。 You must cast back to the correct type.您必须转换回正确的类型。

Also note that this can be complicated if multiple inheritance is involved and multiple casts are used.另请注意,如果涉及多重继承并使用多重转换,这可能会很复杂。 Your casts must "match" in either direction.您的演员必须在任一方向“匹配”。

If your code is structured such that you won't know the type at the time of destruction, give each deletable object a common base class with a virtual destructor.如果您的代码结构使得您在销毁时不知道类型,请为每个可删除对象提供一个带有虚拟析构函数的公共基类。 Then cast back to the base class before delete is called.然后在调用 delete 之前转换回基类。

The code is well-defined.代码定义明确。 Both casts are static casts, although it is good style to make this explicit ( static_cast<void*> , etc. ) instead of using C-style casts.两种类型转换都是静态类型转换,尽管使这种类型显式( static_cast<void*>)而不是使用 C 样式类型转换是一种很好的风格。 The standard says that if a pointer to object is converted to a void pointer and back by static casts, it will keep its original value.该标准表示,如果指向对象的指针被转换为空指针并通过静态转换返回,它将保持其原始值。 Thus, your final delete expression shall have the same effect as delete c .因此,您的最终delete表达式应具有与delete c相同的效果。

That being said, use of void* is often a code smell in C++.话虽如此,使用void*通常是 C++ 中的代码异味。

It is a good practice to set the pointers to nullptr after deletion, especially to avoid access violation / segfault in another thread / event handler. 删除后将指针设置为nullptr是一个好习惯,尤其是为了避免在另一个线程/事件处理程序中访问冲突/段错误。

auto c = new MyCls();
auto p = static_cast<void*>c;
delete static_cast<MyCls*>p;
p = nullptr;
c = nullptr;

It is even better to use smart pointers and avoid new / delete altogether. 使用智能指针甚至完全避免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

In C++, explicit casts such as static_cast is preferred. 在C ++中,首选显式强制类型转换为static_cast

If ~MyCls() is non-trivial, it will be invoked because you cast p to MyCls* . 如果~MyCls()是非平凡的,那么它将被调用,因为你将pMyCls* Deleting a void* won't invoke the destructor, and that could lead to memory leak or other problems. 删除void*不会调用析构函数,这可能会导致内存泄漏或其他问题。

Although this code is valid, it is not good practice.尽管此代码有效,但这不是一个好习惯。

As a general guideline, there shouldn't be new s and delete s in the wild.作为一般准则,在野外不应该有new s 和delete s。 Try to enforce a rule that only constructors can call new and only destructors can call delete will help you organize your code better.尝试强制执行只有构造函数可以调用new并且只有析构函数可以调用delete的规则,这将有助于您更好地组织代码。

If you are using C++11, always try std::shared_ptr and the like, this will do the above automatically for you.如果您使用的是 C++11,请始终尝试std::shared_ptr等,这将自动为您执行上述操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM