Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to prevent the destructor from running when calling delete in C++?

Specifically, in a library, I have a memory pool that overrides the behaviour of new and delete for certain classes. I want users of the library to be able to call delete on instances of those classes, but I need to keep the instances alive until a specific cleanup action at a later time. Is this at all possible while letting the users use regular new/delete? Some way to override the default behaviour of calling the destructor?

like image 613
KillerSponge Avatar asked Dec 19 '22 12:12

KillerSponge


2 Answers

Short answer: no. Calling delete always triggers a call to the destructor, and after that a call to operator delete, the same way as calling new first calls the corresponding operator new and then runs the constructor of the object. If you want to prevent your users from destroying the objects you have to somehow prevent them from a) calling delete on raw pointers and b) construct them on the stack.

If you want to keep the instances alive it sounds like you want to manage their lifetimes, so the natural way would be to also create the objects inside your library in the first place. In addition, having plain delete calls in the code is considered bad style these days anyway, as there are smart pointers available who do those calls automatically.

So what you could do is add creator functions to your library which return some kind of smart pointers. Those could be either shared_ptr or unique_ptrs with a special deleter which does not really delete the object but pass it back to your library to be cleaned up later.

like image 123
Arne Mertz Avatar answered May 13 '23 05:05

Arne Mertz


Use smart pointers instead of new/delete (which is good practice anyway).

Use a custom deleter that moves ownership of the object to a list of "waiting to be cleaned up" objects.

For examples of smart pointers, refer to std::unique_ptr and std::shared_ptr.

Another option (which is more work and harder to get right) is to only store the objects in containers that use custom allocators, and have the allocator's destroy and deallocate functions do the "move to a staging area for cleanup instead of actually destroying it" part. I would recommend the smart pointer with custom deleter approach, not the allocator one.

Both these options (custom deleters and custom allocators) allow you to control the exact behaviour when an object is "destroyed", separating the actual end of the object's lifetime from the moment when users dispose of it, which cannot be done with the delete operator.

like image 34
Jonathan Wakely Avatar answered May 13 '23 04:05

Jonathan Wakely