Chromium的智能指针/引用计数/Callback/Bind

来源:互联网 发布:淘宝5金冠店铺排行 编辑:程序博客网 时间:2024/04/27 20:46

这四个东西对使用者来说不难,看懂代码注释里的例子即可,预计1小时左右看懂全部。要去理解其设计思想的话最需要掌握的是模板类的使用,但一般使用者完全不用关心怎么设计的。

使用者的学习路径:

1.智能删除指针scoped_ptr

用作对普通指针的转储,防止忘记delete或不知道哪里delete。它跟引用计数没有关系。

头文件的注释就是使用示例

http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/scoped_ptr.h

template <class T, class D = base::DefaultDeleter<T> > class scoped_ptr

其中Deleter可以被替换,默认的Deleter区分是要delete普通指针还是指针数组,或者用free函数删除malloc的内存。

2.ScopedVector

http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/scoped_vector.h

在析构时会delete其元素的vector,知道它的行为即可。

3.带引用计数的类

http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/ref_counted.h

为了避免模板类的代码膨胀,引入基类base::subtle::RefCountedBase。基类很简单,就是最基本的引用计数,带AddRef和Release函数。

模板类template <class T> class RefCounted : public subtle::RefCountedBase相对地就只在Release函数内做特殊处理:delete static_cast<const T*>(this)

另外RefCountedThreadSafeBase和模板类RefCountedThreadSafe是线程安全的版本。

4.引用计数的智能指针scoped_refptr

同在ref_counted.h里定义,对RefCounted的子类做引用。scoped_refptr就是构造时调用RefCounted子类的AddRef函数和析构时Release,并提供了操作符的重载。

5.WeakPtr

弱引用指针,用作传递指针但不想更换owner的情况,即明确知道谁去释放但其它引用者不确定其时机,用弱引用指针可随时知道其是否已delete。

http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/weak_ptr.h

看文件里的注释即可。

6.Callback

对函数的闭包封装,头文件的注释就是使用示例

http://src.chromium.org/viewvc/chrome/trunk/src/base/callback.h

要注意注释里提到的对传入参数的要求。Callback最多提供带7个参数的函数封装,其协作类非常多但都不需要去理解。

(理解设计的提示:非常多的模板类,用作抽象各种各样的函数签名;有很多的辅助类和typedef,最好自己整理成图来看清它们的关系)

7.Bind

对Callback的便捷封装,Bind就是返回Callback对象。

http://src.chromium.org/viewvc/chrome/trunk/src/base/bind.h

看看头文件知道它是个模板函数并为不同参数个数做了重载就行了。

(理解设计的提示:查看http://src.chromium.org/viewvc/chrome/trunk/src/base/bind_internal.h文件的注释)



对scoped_ptr的理解:

没有引用计数的类,使用scoped_ptr<class T, class D>。这个模板类中的D是指Deleter,代表如何删除T。引入Deleter最简单的原因就是对数组需要使用delete[]操作符,实际上有4个默认的Deleter。


3个Deleter都是通过重载括号运算符来执行实际的delete操作,而常量长度的数组指针是不允许使用智能指针的,这里也声明出来,能在编译阶段就排除错误。

除了DefaultDeleter,还有一些特殊的Deleter,如disk cache使用的EntryDeleter(disk_cache.h),字节对齐的内存使用的AlignedFreeDeleter(aligned_memory.h),他们都有自己的括号运算符重载实现,因为这是scoped_ptr模板类要求的的方式。

scoped_ptr还有个基类template <class T, class D> class scoped_ptr_impl,它实现了scoped_ptr的核心功能,这样抽离出来是因为有些地方不需要更多的功能。这是模板类,多一个函数就可能多好多个实现。

scoped_ptr_impl定义了内部类Data来继承Deleter,实际就是增加了ptr来保存传入的裸指针(raw pointer / bare pointer)。

struct Data : public D {    explicit Data(T* ptr_in) : ptr(ptr_in) {}    Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}    T* ptr;};Data data_;
scoped_ptr_impl的主要函数:

  explicit scoped_ptr_impl(T* p) : data_(p) { }  ~scoped_ptr_impl() {    if (data_.ptr != NULL) {      // Not using get_deleter() saves one function call in non-optimized      // builds.      static_cast<D&>(data_)(data_.ptr);    }  }  void reset(T* p) {    // This is a self-reset, which is no longer allowed: http://crbug.com/162971    if (p != NULL && p == data_.ptr)      abort();    T* old = data_.ptr;    data_.ptr = NULL;    if (old != NULL)      static_cast<D&>(data_)(old);    data_.ptr = p;  }  T* get() const { return data_.ptr; }  D& get_deleter() { return data_; }  const D& get_deleter() const { return data_; }  void swap(scoped_ptr_impl& p2) {    using std::swap;    swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));    swap(data_.ptr, p2.data_.ptr);  }  T* release() {    T* old_ptr = data_.ptr;    data_.ptr = NULL;    return old_ptr;  }
scoped_ptr是独立的模板类

template <class T, class D = base::DefaultDeleter<T> > class scoped_ptr

template <class T, class D> base::scoped_ptr<T[], D>

它有唯一的成员变量

base::internal::scoped_ptr_impl<element_type, deleter_type> impl_
即是组合scoped_ptr_impl,而不是用继承(也就是桥接模式)。impl有的函数,scoped_ptr都有,并多了重载运算符,以便使用者能直接使用智能指针做其它操作:

typedef T element_type


内存释放的流程:scoped_ptr析构=>impl_析构=>调用deleter=>delete element_type


对引用计数的理解:

有引用计数的智能指针则简单多了:


其中T是本身实现了引用计数的类。


为了避免模板类,引入基类:


基类都是这老一套,用变量保存引用数,没啥说的。

模板类:

template <class T>class RefCounted : public subtle::RefCountedBase { public:  RefCounted() {}  void AddRef() const {    subtle::RefCountedBase::AddRef();  }  void Release() const {    if (subtle::RefCountedBase::Release()) {      delete static_cast<const T*>(this);    }  } protected:  ~RefCounted() {} private:  DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);};

参考:

http://dev.chromium.org/developers/coding-style/important-abstractions-and-data-structures


转载请注明出处:http://blog.csdn.net/hursing

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 员工失去了工作乐趣怎么办 古墓丽影9出bug怎么办 气炉子打不着火怎么办 下面人员不参加公司拓展怎么办 重点班的差生怎么办 江苏考生选修考d怎么办 眼睛里有虫子该怎么办 屋里毛絮特别多怎么办 信用卡人员核核查单位地址怎么办 红米note电源键失灵怎么办 红米note4x跳屏怎么办 红米开机键坏了怎么办 红米note2开关键不灵敏怎么办 大学生论文检测系统忘记密码怎么办 快手实验室没有k歌怎么办 皮肤一到冬天就会起皮脱落怎么办 嘴上的皮撕破了怎么办 身体皮肤干燥起皮怎么办 把公司数据库弄宕机了怎么办 地铁上临时变站怎么办 大学实践课挂了怎么办 军训的人长得矮怎么办 军训脸被晒黑了怎么办 晚上吃了油炸的怎么办 楼梯又陡又窄怎么办 小孩不认真做作业怎么办 水厂出水水质不达标怎么办 野猪铁夹子夹到怎么办 燃气灶开孔尺寸大了怎么办 苹果电脑视频显示缺少插件怎么办 安装拼多多显示校验失败怎么办 中央庭黑盒被抢怎么办 lab值a值偏高怎么办 橱房管道堵死了怎么办 微信被别的手机同步登录怎么办 计算机机房空调坏了怎么办 被蝎子蛰了怎么办怎么处理? 月嫂走了孩子闹怎么办 转业军人自建房有困难怎么办 转业军人没配偶想异地安置怎么办 转业军人档案和身份证不符怎么办