Some more pointing

Instead of answering all the comments about QScopedPointer, I decided it's easier to post a follow-up post :) Thanks to Thiago's blog, the differences between the various smart and not so smart pointers should hopefully be clearer now.

Using QScopedPointer instead of std::auto_ptr or boost's scoped pointer has nothing to do with not-invented-here syndrome. Very early during our API discussions we realized that delete-on-end-of-scope was not enough, we also needed custom cleanup handlers. Take QBrush as example - extra magic is required when deleting the private object. The other pointer classes did not offer that functionality, so they were ruled out.

Why did we make the custom deleters a template argument, and not simply a function pointer member in the class? This has two reasons. Firstly, we didn't want any penalty from using QScopedPointer over manual new/delete. Setting an extra pointer, and calling it in the destructor would have introduced an extra overhead. Secondly, due to our binary compatibility policy, the size of QScopedPointer must be sizeof(void*), so adding another member variable was not possible.

Custom cleaners can be very useful - you can basically use QScopedPointer for any cleanup when leaving scope, for example to close a handle, decrease some reference count, call a custom free function and so on.

Still not in love with QScopedPointer? Let's look at the following, then:

class ForwardDeclared;
extern ForwardDeclared *myFunc();

...
std::auto_ptr<ForwardDeclared> ptr(myFunc());

It compiles, but you'll get a nasty surprise at runtime - since the class is only forward declared, its destructor will not be called on deletion! QScopedPointer has extra protection, forcing a compilation error in the case above.

To make sure that you can write if (myScopedPointer) ..., we had to introduce an operator bool() - but that would also enable writing int x = myScopedPointer;, due to the implicit boolean to integer conversion. Thankfully, we found that issue during an API review, so the latter case will now not compile.

Still not deeply in love with QScopedPointer? Good news - it's all template code, all inline, so there's no penalty to Qt's library size or runtime behavior if you choose to ignore our little gem :)


Blog Topics:

Comments