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.
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.
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.
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.
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).
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 .
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.
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 ashared_ptr
to a statically allocated object, and other variations allow ashared_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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With