Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does delete work with pointers to base class?

Do you have to pass delete the same pointer that was returned by new, or can you pass it a pointer to one of the classes base types? For example:

class Base { public:     virtual ~Base();     ... };  class IFoo { public:     virtual ~IFoo() {}     virtual void DoSomething() = 0; };  class Bar : public Base, public IFoo { public:     virtual ~Bar();     void DoSomething();     ... };  Bar * pBar = new Bar; IFoo * pFoo = pBar; delete pFoo; 

Of course this is greatly simplified. What I really want to do is create a container full of boost::shared_ptr and pass it to some code that will remove it from the container when it is finished. This code will know nothing of the implementation of Bar or Base, and will rely on the implied delete operator in the shared_ptr destructor to do the right thing.

Can this possibly work? My intuition says no, since the pointers will not have the same address. On the other hand, a dynamic_cast<Bar*> should work, so somewhere the compiler is storing enough information to figure it out.


Thanks for the help, everybody who answered and commented. I already knew the importance of virtual destructors, as shown in my example; after seeing the answer I gave it a little thought, and realized the whole reason for a virtual destructor is this exact scenario. Thus it had to work. I was thrown by the absence of a visible means of converting the pointer back to the original. A little more thinking led me to believe there was an invisible means, and I theorized that the destructor was returning the true pointer for delete to release. Investigating the compiled code from Microsoft VC++ confirmed my suspicion when I saw this line in ~Base:
mov eax, DWORD PTR _this$[ebp] 

Tracing the assembler revealed that this was the pointer being passed to the delete function. Mystery solved.

I've fixed the example to add the virtual destructor to IFoo, it was a simple oversight. Thanks again to everyone who pointed it out.

like image 543
Mark Ransom Avatar asked Nov 17 '08 05:11

Mark Ransom


People also ask

Does delete only work on pointers?

In C++, the delete operator should only be used either for the pointers pointing to the memory allocated using new operator or for a NULL pointer, and free() should only be used either for the pointers pointing to the memory allocated using malloc() or for a NULL pointer. It is an operator. It is a library function.

Does Delete Delete a pointer?

delete keyword in C++ New operator is used for dynamic memory allocation which puts variables on heap memory. Which means Delete operator deallocates memory from heap. Pointer to object is not destroyed, value or memory block pointed by pointer is destroyed.

What happens to a pointer when you delete it?

The address of the pointer does not change after you perform delete on it. The space allocated to the pointer variable itself remains in place until your program releases it (which it might never do, e.g. when the pointer is in the static storage area).

Do you need to delete pointers in C?

You don't need to delete it, and, moreover, you shouldn't delete it. If earth is an automatic object, it will be freed automatically. So by manually deleting a pointer to it, you go into undefined behavior. Only delete what you allocate with new .


2 Answers

Yes, it will work, if and only if the base class destructor is virtual, which you have done for the Base base class but not for the IFoo base class. If the base class destructor is virtual, then when you call operator delete on the base class pointer, it uses dynamic dispatch to figure out how to delete the object by looking up the derived class destructor in the virtual function table.

In your case of multiple inheritance, it will only work if the base class you're deleting it through has a virtual destructor; it's ok for the other base classes to not have a virtual destructor, but only if you don't try to delete any derived objects via those other base class pointers.

like image 102
Adam Rosenfield Avatar answered Sep 22 '22 23:09

Adam Rosenfield


This doesn't relate to your given example, but since you mentioned that you're really interested in shared_ptr's behavior when deleting its owned object, you might be interested in using shared_ptr's 'deleter'.

If the object owned by the shared_ptr needs special handling when being deleted, you can specify a 'deleter' for any particular shared_ptr<>. The deleter is not part of the type, it's an attribute of a shared_ptr<> instance, so your container of shared_ptr<> objects could have some objects with different deleters. Here's what the Boost docs say about the shared_ptr<> deleter:

Custom deallocators allow a factory function returning a shared_ptr to insulate the user from its memory allocation strategy. Since the deallocator is not part of the type, changing the allocation strategy does not break source or binary compatibility, and does not require a client recompilation. For example, a "no-op" deallocator is useful when returning a shared_ptr to a statically allocated object, and other variations allow a shared_ptr to be used as a wrapper for another smart pointer, easing interoperability.

It would be cleanest if you could modify IFoo to have a virtual destructor since you're planning to delete objects that are subclasses of it through an IFoo reference or pointer. But if you're stuck with an IFoo that cannot be corrected, then if you want to use shared_ptr<IFoo> in your container, but have it pointing to a Bar, you could create the shared_ptr instance with a deleter that performs a downcast to a Bar* then does the delete operation. Downcasts are considered bad form, but this technique might be something that you could use in a bind.

like image 27
Michael Burr Avatar answered Sep 24 '22 23:09

Michael Burr