webkit内存管理1:智能指针

转载请注明出处: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);

2. 对象创建后,传给 RefPtr 或 PassRefPtr ,引用计数记为1。所以一般是static create创建对象,而构造函数为 private 

3. OwnPtr 提供了一种更普遍的类的管理(指针传递),而 RefPtr 用于引用计数类的管理。 OwnPtr 在离开作用域的时候,自动销毁对象。



参考:






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值