Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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.

share|improve this question
    
delete is an operation that doesn't exist in C (neither in Java or C#)- How could it be unidiomatic in C#? Maybe it could be considered deprecated, though. –  user281377 Mar 13 '11 at 17:01
4  
@ammoQ: delete is necessary, because smart pointers and containers have to be implemented somewhere. I think the question should be: Should they be used in application code, or only in low-level libraries? –  nikie Mar 13 '11 at 19:33
3  
I feel this question belongs on SO, even though it's a tad subjective. –  Johannes Rudolph Mar 13 '11 at 20:57

5 Answers 5

up vote 9 down vote accepted

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).

share|improve this answer
    
Okay I buy the object pool case. –  grokus Mar 13 '11 at 20:45
1  
good point about pools, it's why I prefer to refer to smart managers rather than smart pointers, the latter being too limited. A number of pools though will give you a handle rather than a pointer, which is especially handy for debug modes (as the handle can provide a number of checks, like making sure you're not accessing a deleted object), or if you want reference counting on your object (which is akin to smart pointers). –  Matthieu M. Mar 14 '11 at 7:14

Not every piece of software needs to use smart pointers. Depending on the smart pointer implementation and on the application at hand, they can actually cause more trouble than they are worth.

In some situations you'll find that a given object owns another object completely for it's entire lifetime. At which point, introducing a smart pointer to delete something that can easily be deleted in the owner's destructor may not be all that useful.

Older apps that have been 'brought forward' into the C++ era often don't have smart pointers either. These things started out without objects, and were hammered on until they had objects in them. These apps often have some seriously idiosyncratic behavior and design, and smart pointers may simply not be a part of it.

Containers of pointers may also not be done with smart pointers because (again, depending on the available smart pointer implementation), they may do odd things to the access patterns of the contained objects.

The biggest reason a given application doesn't have smart pointers is simply that the original author wasn't familiar with them, and/or didn't have a smart pointer implementation that they liked. It's not any indication of the quality of the surrounding code.

share|improve this answer
    
(1) For the one object owns another object case, a scoped_ptr works pretty well. (2) I don't see any advantage of using raw pointers over shared_ptr in a container. –  grokus Mar 13 '11 at 21:00
    
(2) Some smart pointers make indirections look odd in containers. I haven't used shared_ptr, that one probably doesn't, so it may well be a good fit. Also, if one's first experience with 'smart' pointers was with auto_ptr, one gets into the habit of not trying anything too fancy. –  Michael Kohne Mar 14 '11 at 1:42
    
(1) I just tend to think that in these simple cases where ownership is well established, adding yet another object isn't worth the trouble. But that's a personal preference. –  Michael Kohne Mar 14 '11 at 1:42

Yes. If it's designed now.

If it's been designed before their advent, nothing should prevent you from replacing the manual handling by smart managers.

The question is not:

Should I be using smart managers here ?

But:

Which smart manager fits best ?

If a modern piece of code is written without smart managers, it's an indication that the author is not up-to-date on C++ practices, and I would be very worried about the exception safety aspect....

share|improve this answer
1  
Smart points do not guarantee exception safety either. –  quant_dev Mar 13 '11 at 20:51
1  
@quant_dev: and I did not say so. However they are a tremendous step toward guaranteeing Basic Exception Safety, which is about not leaking resources even in the face of exception. Without them, even if the code is littered with try/catch, you'd better worry about its behavior in this regard. –  Matthieu M. Mar 14 '11 at 7:07

I think there are valid reasons for using delete manually, especially if you have to interface libraries that don't use smart pointers, or a set of libraries that use different smart pointer types. But this should be the exception, not the rule. If you can replace the manual delete with a smart pointer, you should.

share|improve this answer

At the moment, there is a lack of smart pointers in the C++ standard library, and Boost can't always be used, so until C++0x delete will be necessary.

Revisiting old code that works is pointless, irrespective of the evolution of idioms.

Even with a good set of smart pointers, you probably won't want to use them if the whole point of your code is to implement a data structure that isn't provided by the C++ standard library, among a few other special cases, so delete will always be needed in some library code.

A point worth considering - smart pointers can have issues with reference cycles. If your objects may have reference cycles, using smart pointers is likely to cause a memory (and potentially resource) leak. Using a smart pointer can be wrong, or at least cause complication for no practical benefit, in some rare special cases.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.