C++ Design – Is Manually Deleting Objects a Sign of Poor Design?

cobject-oriented

With the advent of smart pointers, is it a sign of poor design if I see objects are deleted? I'm seeing some software components in our product that people are still doing this. This practice strikes me as un-idiomatic, but I need to be sure this is the industry consensus. I'm not starting a crusade but it'd be nice to be prepared theory wise.

Edit: legit uses of delete, Klaim mentioned the object pool use case. I agree.

Bad examples of using delete, I am seeing many new's in constructor or start() and corresponding delete's in the destructor or stop(), why not use scoped_ptr? It makes the code cleaner.

Best Answer

Short answer : that depends, and using smart pointers systematically is just wrong. Think first. I'm using smart pointers for a lot of things but it's not right for everything, ie. no silver bullet. You'll have to understand your specific implementation to understand if it's wrong or not. I'm giving some examples in the ...


Long answer :

What makes a software poor, regarding object lifetime, is only the lack of clear and precise control.

C++ letting you define the lifetime of objects mean that the programmers have to setup ways to manage those lifetimes, how different they could be and how easy it is to change it.

I know a lot of cases where smart pointers are just the wrong answer (or overkill), starting with objects in pools. If objects are managed inside a "master" object that will do the new and delete called in an isolated way, then that's fine. Don't forget that smart_pointers, like any other techniques, only hide deletes in a manageable way. To achieve this, they just make clear when the delete will be called and make it a rule.

So, the idea here is that as far as the delete call is put in one place, easy to find, easy to understand, etc. and that it's obvious that people who wrote the code did want the rules of deleting the object to be uniform (no delete hidden in a "special case" code), then it's not poor software design.

Smart pointers are meant to be the "easy answer" to a range of cases where you can't be sure where the delete call should be done. So you have to define how to delete it and define a rule that trigger this delete. Shared pointers delete once there is no reference to the object. Scoped pointers delete once out of scope. etc. It's easy to use and solve a lot of cases.

But as every tool, it's not silver bullet. As said previously, you can't provide smart pointers for objects allocated in pools. In video games, you often "know" precisely how much objects of each types are allowed at the same time, and the frequency of creation/destruction of those objects. So why do new and delete in this case? You just need to new all the objects in raw memory, use them and delete everything at the end, or just dump the raw memory.

In fact, almost all choices in those cases are driven by hardware or safety or other constraints.

There are no hard and fast rules, just good solutions to specific problems. Especially in C++ as you're the one in charge, not a VM.

If you feel a code smell about your specific case, it might be because the delete calls are done in special or specific cases, not in a generic way. That is poor design. Another thing that should smell is if new and delete are done while there is no good reason to use heap memory instead of stack one. The obvious case is if an object is created and destroyed in the same function. The only case where new/delete is valid then, is if the object requires more memory than the stack allows (and that does happen!).

So, just try to understand exactly why those deletes happen where they do, and if there's no good reason for them being there, you should refactor (if possible).

Related Topic