On 12/10/2006, at 3:14 PM, Erik de Castro Lopo wrote:

I prefer smart design to the C++ template foo around smart pointers.
For instance, if a class can be designed to behave in an RAII way,
much pointer hackery can be localised and thereby made safe.

Sure, if the heap allocation is localised to be a protected/private member in a class, you don't need to use a smart pointer at all since you can destroy the heap object yourself in the destructor. However, once you actually need to pass around that object and share it with other objects, you have questions about object ownership, and that's when smart pointers come into their own. They really are quite magical for this: heap management goes from being a hard problem that requires programmer attention to nearly being a non-issue. I think smart pointers are by far the best heap management solution available short of true garbage collection.

As well as the obvious memory management help, you get a number of more subtle but very good benefits from using them:

* Using smart pointers forces you to think about your object ownership model. For cineSync, we really didn't have a clear model for who owned what objects, and now we do. This is arguably a good thing.

* Using a boost::shared_ptr vs a boost::weak_ptr instantly indicates whether you own or don't own the object. This is great since it's indicated in the type, which means you have a 1:1 mapping between your object ownership model and your code. No need to write extra documentation or comments about it, nor start dictating some sort of naming scheme, since the type says it all. This follows rule #1 of Rusty's interface rules.

* If you start writing a class that doesn't contain smart pointers, it's easy to convert them to be smart pointers if you want those objects to be shared later. boost::shared_ptr provides sensible overloading of the -> and * operators.

You can always argue that instead of using a shared_ptr template, you could just declare your own small value object that hides all the details of the heap allocation from the user. However, you still face the problem of managing the memory for that heap-allocated object when you implement that wrapper object, so it's not like you don't have to deal with the problem. It's tricky to get the details of this implementation right (especially once threads enter the picture): I'd argue it's far more sensible to re-use boost::shared_ptr than to try to implement one yourself. (There's also boost::instrusive_ptr, which can work with existing reference- counting implementations.)

I realise that all this C++ template foo is very tricky, but
it *really* doesn't aid clarity. Code is written once and
read thousands of times. Template code often looks like line
noise to me.

Having delved into the realm of template hackery now, it's not that bad. Templates can always be abused, of course, but if they're used for Good (as in the case of the STL container classes and boost::shared_ptr), they keep compile-time check checking and sacrifice no runtime speed (which is a primary goal). Just _using_ template classes is pretty easy: it's writing template classes and template functions that's a bit harder. Sometimes it's really not worth the hassle to make things templates, but sometimes they clearly aid maintainability rather than making it worse.


--
% Andre Pang : trust.in.love.to.save  <http://www.algorithm.com.au/>



_______________________________________________
coders mailing list
coders@slug.org.au
http://lists.slug.org.au/listinfo/coders

Reply via email to