转载请注明出处:http://blog.csdn.net/awebkit
对于 c/c++ 开发来说,内存管理是一个头疼的问题。那么, WebKit 是如何来管理内存的呢?
首先,我们来学习一下 WebKit 中的智能指针,这是内存管理一个很基础的部分。
在小项目中,大家遵循内存一个申请对应一个释放的原则,基本能解决内存管理问题。但是对于一个大项目,简单靠程序员的自觉性是不够的,因此, WebKit 借鉴 c++ 的智能指针,引入了自己的智能指针管理类 RefPtr PassRefPtr等。由于我本身对 c++ 的智能指针不是很熟悉,因此,不好比较。不过,对于 WebKit 的这些智能指针,我得说,他们足够简单有效。
RefPtr
RefPtr 是一个模板,参数类需要有 ref 和 deref 函数,而 RefCounted 类实现了这两个接口,所以参数类大多继承于 RefCounted 。
如果不使用 RefPtr ,使用裸指针,则代码大概是这样的
// example, not preferred style
class Document {
...
Title* m_title;
}
Document::Document()
: m_title(0)
{
}
Document::~Document()
{
if (m_title)
m_title->deref();
}
void Document::setTitle(Title* title)
{
if (title)
title->ref();
if (m_title)
m_title->deref();
m_title = title;
}
是不是很烦?还容易忘记,写错等。
有了 RefPtr 的代码大概是这样的
// example, not preferred style
class Document {
...
RefPtr<Title> m_title;
}
void Document::setTitle(Title* title)
{
m_title = title;
}
但是,单独使用 RefPtr 会造成引用计数的 震荡。
// example, not preferred style; should use RefCounted and adoptRef (see below)
RefPtr<Node> createSpecialNode()
{
RefPtr<Node> a = new Node;
a->setSpecial(true);
return a;
}
RefPtr<Node> b = createSpecialNode();
For purposes of this discussion, lets assume that the node object starts with a reference count of 0 (more on this later). When it’s assigned to a , the reference count is incremented to 1. The reference count is incremented to 2 to create the return value, then decremented back to 1 when a is destroyed. Then the reference count is incremented to 2 to create b , and then decremented back to 1 when the return value of createSpecialNode is destroyed.
总之,你看到引用计数是在不断的变化。为了解决这个问题,引入了 PassRefPtr
PassRefPtr
PassRefPtr 和 RefPtr 在一点上有所不同。在赋值时,原指针设置为0。整个操作不涉及引用计数的改变
// example, not preferred style; should use RefCounted and adoptRef (see below)
PassRefPtr<Node> createSpecialNode()
{
PassRefPtr<Node> a = new Node;
a->setSpecial(true);
return a;
}
RefPtr<Node> b = createSpecialNode();
解释:
The node object starts with a reference count of 0. When it’s assigned to a, the reference count is incremented to 1. Then a gets set to 0 when the return value PassRefPtr is created. Then the return value is set to 0 when b is created.
但是这样可能会引起别的问题
// warning, will dereference a null pointer and will not work
static RefPtr<Ring> g_oneRingToRuleThemAll;
void finish(PassRefPtr<Ring> ring)
{
g_oneRingToRuleThemAll = ring;
...
ring->wear();
}
ring 已经为0了,还操作?
所以,要混合操作:建议参数和返回值用 PassRefPtr ,local 用 RefPtr
static RefPtr<Ring> g_oneRingToRuleThemAll;
void finish(PassRefPtr<Ring> prpRing)
{
RefPtr<Ring> ring = prpRing;
g_oneRingToRuleThemAll = ring;
...
ring->wear();
}
其他注意事项
1. 裸指针通过 adoptRef 传递指针到 RefPtr 进行管理
// warning, requires a pointer that already has a ref
RefPtr<Node> node = adoptRef(rawNodePointer);
3. OwnPtr 提供了一种更普遍的类的管理(指针传递),而 RefPtr 用于引用计数类的管理。 OwnPtr 在离开作用域的时候,自动销毁对象。
参考: