[after setting c=null] object still in the memory and nothing points at it. How
we gonna delete it?
You can't -- in that case your program has a type of bug called a memory leak
, because without a pointer to the object, you have no way to delete the object you allocated. If you don't want your program's memory usage to grow over time (and potentially exhaust its host computer's RAM at some point), it's important to preserve at least one pointer to each object you have dynamically allocated, precisely so that you can retain the ability to delete
the object when you're done using it.
[in the other case] we delete an object, but pointer still points to address
location of previous object. In which cases that may be useful?
Having a pointer to a deleted object is almost never useful -- trying to dereference the pointer will cause undefined behavior
, and technically even reading the value of the dangling pointer (without dereferencing it) is a no-no as well(!). The only reason not to set the pointer to NULL is because setting the pointer to NULL would take an extra CPU instruction (and an extra write to memory) to perform, and C++ tries not to force you to pay overhead costs that you don't need to pay. So if you can guarantee that you will never try to use the "dangling pointer" after you've deleted the object, it's very slightly more efficient to not set it to NULL than it would be to set it to NULL for no reason.
If all of the above seems a bit programmer-unfriendly to you, you're absolutely right -- it is. Raw pointers demand very exacting behavior from the programmer, and if the programmer doesn't handle them 100% correctly, the result is a buggy program (with memory leaks, or crashes at runtime, or other undefined but undesirable behavior). If you'd prefer to avoid that kind of risk (and you should!) then instead of holding your dynamically-allocated object using a raw pointer (e.g. Class *
), you can hold it using a "smart pointer" like std::unique_ptr
or std::shared_ptr
. The smart-pointer classes will give you the "it automatically does the right thing" behavior that raw pointers do not, at the cost of adding an insignificant amount of overhead to your program.