Smart pointers: A dumb idea?
A while ago I wrote a smart pointer for Nova and I have been wondering on whether or not I should use it. And if I did choose to use it to what degree.
Smart pointers are useful, I use the boost variant often enough, but like everything you shouldn’t fully depend on it. Pointers are in many cases good enough. The only thing why smart pointers are so useful is that you don’t have to worry about the lifetime of the object (when the object is destroyed).
In many cases the only time you worry about is when data needs to be shared, for example a texture, as you don’t want to load the same data twice. But another simple technique is the IUnknown interface which creates an object that will delete itself when it has been released as many times as it was created. You still don’t have to worry about the lifetime of the object, you only have to remind you to call release when you no longer need an object. If nothing requires that object the call to release will cause it to delete itself.
Here is the basic code:
[cc_cpp]
/* IBaseObject.h */
class IBaseObject{
private:
unsigned int m_ReferenceCounter;
protected:
IBaseObject();
public:
virtual ~IBaseObject() = 0;
unsigned int AddRef();
unsigned int Release();
};
/* IBaseObject.cpp */
#include "IBaseObject.h"
IBaseObject::IBaseObject() : m_ReferenceCounter(1)
{
}
IBaseObject::~IBaseObject() {}
unsigned int IBaseObject::AddRef(){
return ++m_ReferenceCounter;
}
unsigned int IBaseObject::Release() {
--m_ReferenceCounter;
if(m_ReferenceCounter == 0)
{
delete this;
}
return m_ReferenceCounter;
}
[/cc_cpp]
After some thought on the issue I have decided that IUnknown is far superior to a smart pointer. The majority of the smart pointers I have encountered and written work on the same basic principle. Each smart pointer has a pointer to the object and also a pointer to an integer in which you store the amount of copies. That means that if you look at the code it will look something like this:
[cc_cpp]
template
class smart_ptr
{
T* m_Data;
unsigned int* m_Copies;
};
[/cc_cpp]
When you think about how smart_ptr really works, you will think how stupid the idea is. For every copy of the object you will have two extra pointers, assuming 32 bit system, that would be 8 bytes extra for every copy.
The second issue is a bit more hidden but if you have this function:
[cc_cpp]
class CObject; // Just an object
void accidental_copy(smart_ptr
[/cc_cpp]
You will be making an copy of the object, which means that you will have an extra construct and destruct function to take in account. Which means that a smart pointer not only increases the amount of memory needed, but also reduces the speed. With a pointer you won't have the above problems.
There is however one huge advantage that a smart pointer has but IUnknown doesn't: Smart pointers can work with virtually any type while to use IUnknown the object needs to be derived from it. However since I'm writing the code for Nova I can just make sure that all objects derive from IUnknown.
To add an conclusion, I have decided to before using smart pointers I should first try and see if there is another solution.