webkit技术译文系列(二):RefPtr和PassRefPtr基础
来源:互联网 发布:招聘java工程师的要求 编辑:程序博客网 时间:2024/04/29 05:19
原文链接:http://webkit.org/coding/RefPtr.html
历史
WebKit中的许多对象是引用计数的(reference counted),采用的模式就是类具有ref和deref成员函数增加和减少引用计数。每个ref调用必须有一个deref与之匹配。当在引用计数值为1的对象上调用deref方法时,对象删除。WebKit中的许多类通过继承RefCounted类模板应用该模式。
时间回溯到2005年,我们发现存在许多由于不正确调用ref和deref而引起的内存泄露,特别是HTML编辑的代码。
我们希望使用智能指针来减少这一问题。但是早期的试验表明智能指针会进行额外的引用计数处理而影响性能。例如,一个函数有一个智能指针的参数并返回该指针指针作为返回值,仅仅传入该参数并返回该值会进行2到4次的增加和减少引用计数值,因为对象从一个智能指针转移到另一个上。因此我们寻找一种方式来让我们使用智能指针同时避免引用计数跳变(churn).
我们从C++标准类模板auto_ptr获得灵感,这些对象实现了一种模型,赋值即是归属关系转移(transfer of ownership),当您从一个auto_ptr赋值到另一个,贡献值变成0.(When you assign from one auto_ptr to another, the donor becomes 0.)
Maciej Stachowiak设计了一对类模板,RefPtr和PassRefPtr,实现这一模式来解决WebKit中恼人的引用计数问题。
原始指针(Raw pointers)
当我们讨论诸如RefPtr类模板之类的智能指针时,通常使用原始指针(raw pointer)指代C++语言中内置的指针类型。下面是经典的使用原始指针(raw pointer)的设置函数:
- // 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
RefPtr是一个简单的智能指针类,它对来值(incoming value)调用ref,对去值(outgoing value)调用deref。RefPtr可用于任何有ref和deref成员函数的对象。下面是使用RefPtr写的设置函数实例:
- // example, not preferred style
- class Document {
- ...
- RefPtr<Title> m_title;
- }
- void Document::setTitle(Title* title)
- {
- m_title = title;
- }
单独使用RefPtr可能会导致引用计数跳变(churn)。
- // 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();
出于讨论考虑,我们假设节点对象的引用计数起始值为0(稍后更多),当它赋值给a后,引用计数值增加到1。创建返回值后引用计数值又增加到2,接下来a销毁,引用计数值又减少到1。然后创建b后引用计数值增加到2,再下来createSpecialNode返回值销毁后,引用计数值减到1。
(如果编译器实现了返回值优化(return value optimization),就会少一次引用计数增加和减少。)
引用计数跳变(churn)在函数参数和返回值都涉及的情况下更严重,解决的方法就是PassRefPtr。
PassRefPtr
PassRefPtr和RefPtr相似,但存在一处不同,当您拷贝一个PassRefPtr或者赋PassRefPtr值给RefPtr或另一个PassRefPtr时,原来的指针值设置为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();
节点对象的初始引用计数值为0,当它赋值给a后,引用计数值增加到1
- webkit技术译文系列(二):RefPtr和PassRefPtr基础
- webkit技术译文系列(二):RefPtr和PassRefPtr基础
- [WebKit]RefPtr和PassRefPtr基础
- [WebKit]RefPtr和PassRefPtr基础
- [WebKit]RefPtr和PassRefPtr基础
- [WebKit]RefPtr和PassRefPtr基础[1]
- [WebKit]RefPtr和PassRefPtr基础[1]
- [WebKit]RefPtr和PassRefPtr基础[1]
- WebKit中的RefPtr和PassRefPtr
- RefPtr和PassRefPtr基础[1]
- WebKit中RefPtr和PassRefPtr的使用
- WebKit里的RefPtr和PassRefPtr
- WebKit中RefPtr和PassRefPtr的使用
- WebKit中RefPtr和PassRefPtr的使用
- webkit智能指针 - RefPtr, PassRefPtr(adoptRef)
- RefPtr and PassRefPtr基础 -- WebKit中的引用计数
- Webkit RefPtr and PassRefPtr Basic
- webkit智能指针 - RefPtr, PassRefPtr
- Visual Studio 2008项目系统属性中的宏
- JAVA位运算符
- DBI接口与DPI接口
- Linux再一次整理
- 进程和线程
- webkit技术译文系列(二):RefPtr和PassRefPtr基础
- 剑法三套,程序员也能挣大钱(一)
- WebKit中的设计模式(一): Noncopyable
- Siverlight 应用标准的WCF开发应用程序,WCF+LINQ+SL LINQ动态查询(今日随笔)
- 剑法三套,程序员也能挣大钱(二)
- WebCore中的渲染机制(一):基础知识
- 剑法三套,程序员也能挣大钱(三)
- 如何给多个子系统设计一个简单通用的权限管理方案?(详细讲解及源代码下载)
- EXT3与EXT4的主要区别