博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WebKit源代码里的RefPtr智能指针
阅读量:6442 次
发布时间:2019-06-23

本文共 1660 字,大约阅读时间需要 5 分钟。

WebKit源代码里的RefPtr智能指针的一些心得。

Overview

WebKit的智能指针由类族 RefPtr 来实现,其核心由三个类组成:

  • RefCounted
  • RefPtr
  • PassRefPtr

其中RefCounted提供了引用计数器(一个int型成员),而RefPtr和PassRefPtr则提供了自动管理引用计数器的功能。根据的说法,最初并没有RefPtr和PassRefPtr,这两个类是2005年才加入的,在它们出现之前完全是靠找死的人工管理RefCounted的引用计数。RefCounted类本身是没有问题的,但它的使用方法相当繁琐,繁琐到开发人员发现很多内存泄露都是由于对方法ref()和deref()的调用不当而造成一半以上内存泄露的程度。为了简化RefCounted的使用方法,RefPtr诞生了,而为了更高效地传递参数,开发人员又创造了PassRefPtr。

RefCounted

RefCounted的源代码在这里:。

这个文件里定义了两个类:非模板类RefCountedBase和模板类RefCounted,从名字上就能看出来RefCounted继承于RefCountedBase。像维护引用计数器这么简单的活儿只使用一个类就绰绰有余了,这里之所以做成两个类是为了减少template hoisting(实例化模板导致的代码膨胀)。总而言之,最终的RefCounted完成了这样的功能:

  • 定义了成员变量:int m_refCount
  • 定义函数ref
    1
    2
    3
    4
    5
            
    //
    void 
    ref()
    {
        
    ++m_refCount;
    }
  • 定义函数deref
    1
    2
    3
    4
    5
    6
            
    //
    void 
    deref()
    {
        
    if 
    (derefBase())
            
    delete 
    static_cast
    <T*>(
    this
    );
    }
    derefBase的定义是:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
            
    //
    // Returns whether the pointer should be freed or not.
    bool 
    derefBase()
    {
        
    if 
    (m_refCount == 1) {
          
    return 
    true
    ;
        
    }
     
        
    --m_refCount;
        
    return 
    false
    ;
    }

上面的ref()和deref()就是RefCounted的核心功能了,不过有一点要注意的是RefCounted的析构函数是protected的,这样就不能直接定义RefCounted对象了,而是必须从RefCounted继承子类才能行。但是这里不同于一般的继承,这里玩了个小trick:

1
2
3
class 
Frame :
public 
RefCounted<Frame> {
  
// ...
}

和一般的继承不一样吧,之所以要写成这样的原因在于函数deref()能够删除正确的对象!在函数deref()里,如果计数器到了1,就必须把自己销毁(即delete this),但此时的RefCounted直接来一句delete this是不对的,因为如果有一个类Foo继承于RefCounted,那在RefCounted的成员函数里调用delete this只会触发RefCounted的析构函数,而不会触发Foo的析构函数。为了让RefCounted在delete this时能确定子类的类型,类Foo就得从RefCounted<Foo>继承,这样才能为在RefCounted中delete this提供便利:

1
delete 
static_cast
<T*>(
this
);

在编译时T的类型会被确定为Foo,因此上面这句代码会触发Foo的析构函数,另外由于Foo继承于RefCounted,RefCounted的析构函数随后会调用(虽然啥也没干)。

转载于:https://www.cnblogs.com/justinyo/archive/2013/04/14/3020640.html

你可能感兴趣的文章
js数据类型只string,object
查看>>
android httpClient(https/http)的优化构建方式二
查看>>
架设用Webservice实现文件上传功能CentOS服务器(一)--Tomcat
查看>>
一步一步部署Laravel项目
查看>>
.net 2.0 4.0 表单中危险字符
查看>>
dubbo负载均衡策略
查看>>
玩转大数据系列之Apache Pig如何通过自定义UDF查询数据库(五)
查看>>
axis实例包
查看>>
归并排序 MergeSort
查看>>
Javascript的this用法
查看>>
Fiddler下Firefox提示“您的连接并不安全”的解决办法
查看>>
mint 安装emacs 24.3源码安装
查看>>
性能细节1
查看>>
Echarts图表
查看>>
Java线程面试题 Top 50
查看>>
解决mysql图形管理器乱码问题
查看>>
mysql :error while loading shared libraries: libaio.so.1: cannot open shared object file:
查看>>
我的友情链接
查看>>
我与51CTO的战争之还有人不依不饶
查看>>
使用FUSE挂载HDFS流程及错误集锦
查看>>