历史
2005年之前,Webkit中很多对象都采用引用计数的方式。它们通过继承RefCounted类模板来实现这种模式。RefCounted主要是实现了ref()和deref()两个函数。在需要引用对象时要调用ref()增加引用计数,在不再需要对象时,要调用deref()函数减少引用计数。ref()和deref()需要成对出现。这和使用new/delete一样,多调用、少调用、没调用的问题总是时有发生。如果能由编译器自动完成ref, deref的调用,C/C++编程的bug至少也可以减少一半以上了。
ps:虽然C/C++编程的大部分问题最终表现是内存问题,但其实根源可能还是逻辑和流程问题。话说回来,如果编译器能自动管理内存,确实可以大大减轻程序员的负担。RefCounted几个主要的函数实现如下:
void ref()
{
++m_refCount;
}
// Returns whether the pointer should be freed or not.
bool derefBase()
{
unsigned tempRefCount = m_refCount - 1;
if (!tempRefCount) {
return true;
}
m_refCount = tempRefCount;
return false;
}
void deref()
{
if (derefBase())
delete static_cast<T*>(this);
}
RefPtr
RefPtr可以应用于任何具有ref()和deref()成员函数的对象,它通过自动调用对象的ref()和deref()来实现指针的智能管理。Webkit中很多对象通过继承RefCounted实现引用计数模式(拥有ref()和deref()函数)。
RefPtr在传入值时自动调用ref()来增加引用计数,在传出值时自动调用deref()来减少引用计数。我们知道在调用deref()时,如果引用计数为1,就会删除相应对象。
RefPtr是用来管理指针的,也就是说你得先有指针吧,指针怎么来的,万变不离其中,还得new出来。new 出来的我们叫裸指针,所谓交给RefPtr管理就是把new出来的裸指针传递给一个RefPtr对象。智能指针内部呢,会在合适的时候delete你交给它管理的裸指针。
通过adoptRef()把一个裸指针赋值给一个RefPtr。任何时候,new对象时都应该立即调用adoptRef,这样就不会有过后忘记调用deref()的问题。
RefPtr<Foo> foo = adopt