开发者

Initialize C++ pointers to ZERO after we delete?

开发者 https://www.devze.com 2023-02-19 04:23 出处:网络
In C++ we use del开发者_JS百科ete operator to delete objects most of the time. The delete doesn\'t make pointer value NULL. Is there any way this can be achieved automatically?

In C++ we use del开发者_JS百科ete operator to delete objects most of the time.

The delete doesn't make pointer value NULL. Is there any way this can be achieved automatically?

e.g.

int *p = new int;
delete p;  // this should deallocate object pointed by p
           // and also initialized value of p = NULL


There are two issues with your suggestion.

A False Sense of Security

Your proposal induce a false sense of security. Sure, the standard guarantees that if you call delete on a null pointer, it won't blow up. However, you have forgotten one tiny fact: there is not a single pointer to your object.

int* p = new int(8);
int* q = p;
delete p; p = 0;
delete q; // Undefined Behavior

Therefore, this practice is useless. And because a false sense of security is worse than no security at all, I actually strongly discourage it. In the hope that people will think before applying delete nilly-willy.

Which brings us to the second issue

Don't you ever dare using delete

delete should be reserved to implementers of smart pointers or other containers. The following apply:

  • For Expert Only
  • (Experts) Don't*

*There's probably an already existing debugged implementation for what you're trying to achieve.

There are heaps of existing tools to manage memory:

  • the ubiquitous various flavors of smart pointers: std::unique_ptr or std::auto_ptr (depending on your version of C++), std::scoped_ptr, std::shared_ptr (and its comparse std::weak_ptr, or their boost/tr1 equivalent)
  • the ubiquitous various flavors of containers: boost::array, boost::scoped_array, std::vector (and co)
  • and the lesser known, but so useful in OO: boost::ptr_vector (and co)
  • there's even boost::intrusive_ptr and the Boost Intrusive Containers library or the Boost MultiIndex library (with the BiMap derivative)
  • and probably several other boost libraries, perhaps more specialized, like Boost.Signals

With such an heterogeneous wildlife, it's hard to think that you suddenly discovered a new way of using data that is so different from what we do that you would need something else. And if you have, feel free to post it, we'll help you understand how to use those tools to fit your situation (or give you pointers on how to create a new form of smart pointer).


It doesn't help much anyway, because there could be more than one pointer to the deleted object.

int* p = new int;

int* q = p;

delete p;   // how do we NULL q?

The best idea is to use delete just before p goes out of scope. Or use standard containers so we don't need new/delete at all.


You could write your own wrapper function or macro that would do that. However, it's hard in the general case, because you can pass rvalues to the delete operator. And then what should it assign NULL to?


without any testing whatsoever, I give you this:

template <typename T> void deleteAndNull(const T*& pointer){
    delete pointer;
    pointer = 0;
}


May be a using auto_ptr with pointers will alos save your time.


It is simple to write one like this:

template<class T>
void safe_delete(T*& p)
{
    delete p;
    p = NULL;
}
int main()
{
    int* p = new int;
    safe_delete(p);

    double* p1 = new double;
    safe_delete(p1);

}

Be careful not to use this with arrays though :)


You could write your own function to do it:

void deleteAndReset (void** p)
{
    delete *p;
    *p = null;
}


Same answer as your other pointer question - use a smart pointer. There's no point reinventing wheels.


Doing that is incredibly bad practice.

They said it would save your program from crash if there is double-deletion. Alas, making pointer NULL after you deleted object it pointed to, just mask the problem: your program contains bug.

I'm assure you that you want you program to crash as early and as loudly as possible in that case.


The easiest way to do this would be to override the operator delete to

  • erase memory
  • Null out the pointer

Read up on operator overloading, is my recommendation. That way, you can preserve all your current code and not have to go through the effort of having to change everything to a function call.

0

精彩评论

暂无评论...
验证码 换一张
取 消