文一:

转:http://wangjun-1985.spaces.live.com/blog/cns!E9070276AAF56C8E!472.entry

在android中可以广泛看到的template<typename T> class Sp句柄类实际上是android为实现垃圾回收机制的智能指针。智能指针是c++中的一个概念,因为c++本身不具备垃圾回收机制,而且指针也不具备构造函数和析构函数,所以为了实现内存(动态存储区)的安全回收,必须对指针进行一层封装,而这个封装就是智能指针,其实说白了,智能指针就是具备指针功能同时提供安全内存回收的一个类。当然,智能指针的功能还不只这些,想了解更多大家可以去研究下~

智能指针有很多实现方式,android中的sp句柄类实际上就是google实现的一种强引用的智能指针。我没有仔细看android sp的实现方式,但其基本原理是固定的,现在我们从一个相对简单的例子来看智能指针的实现:

首先看一个最简单的对指针的封装:

Template <typename T>

class SmartPtr{

public:

SmartPtr(T *p = 0):ptr(p){}

~SmartPtr(){delete ptr ;}

private:

T*ptr ;

};

通过上面的封装,我们就可以用下面的方式来使用SmartPtr而不需要担心内存泄露的问题:

SmartPtr<int> pointer(new int) ;

*(pointer.ptr) = 10 ;

为了方便使用,我们可以对操作符进行重载,让智能指针的操作更像是指针:

T&operator*(){return *ptr}

T* operator->(){return ptr}

经过上面的重载,我们就可以像使用真正的指针一样而不需要去解决内存泄露问题。

因为智能指针封装了指针,所以必须为其实现拷贝构造函数和“=”操作符重载。因为如果不提供这两个函数,当上面的智能指针进行赋值的时候必然会使指针指向同一个区域,一旦析构的话会导致同一个指针被delete两次。

在这里,拷贝构造函数的实现是有技巧的,使用拷贝构造函数创建一个新的只能指针时,并不建立新的对象,而是让新的智能指针指向同一个对象,实际上就是常说的浅复制。但是这样的话就会导致多个指针指向同一块内存区域,当调用析构函数的时候如何来保证同一块内存区域只会被delete一次呢,这里实现的方法有很多,最常用的是引数控制。即在智能指针中加入一个计数器,每次增加一个对内存区域的强引用,则计数器加一,当计数器为0时,这个对象就可以被删除了,这个计数器采用动态分配跟指针分开存储,因为这个计数器是多个智能指针需要共享的:

Template <typename T>

class SmartPtr{

public:

SmartPtr(T *p = 0):ptr(p){count = new int(1) ;}//第一次创建的时候,引数肯定是1

SmartPtr(const SmartPtr & rhs):ptr(rhs.ptr),count(rhs.count){++*rhs.count ;}

T&operator*(){return *ptr}

T* operator->(){return ptr}

SmartPtr&operator=(const SmartPtr & rhs){

if(ptr == rhs.ptr)

return *this ;

if(--*count == 0){


delete ptr ;

delete count ;

}

++*rhs.count ;

count = rhs.count ;

ptr = rhs.ptr ;


}

~SmartPtr(){

if(--*count==0)

delete ptr ;

delete count ;

}

private:

T*ptr ;

int*count ;

};

这样,一个智能指针就基本成形了,当然这只是最简单的智能指针,商业库提供的智能指针都提供非常强大的功能,如果能仔细研究透了android在这方面的实现,应该在c++内存控制方面很有长进~~暂时还没有时间,还要顺着camera往下看,有牛人懂的话email多指教哈~~

出了智能指针sp外,android里面还出现了wp这个指针类,实际上他是一个弱引用类型的指针类,弱引用是在.net以及java中经常用到的,弱引用是一个对象引用的持有者,使用弱引用后可以维持对对象的引用,但是不会阻止其被垃圾回收。如果一个对象只有弱引用了,那它就成为被垃圾回收的候选对象,就像没有剩余的引用一样,而且一旦对象被删除,所有的弱引用也会被清楚。弱引用适合那些数据成员特别多,而且重新创建又相对容易的类,也就是俗称的胖子类,建立弱引用可以引用对象,但也不阻止其被垃圾回收,在内存的使用方面取得一定的平衡。

在android中wp类里面的promote函数实际上就是将一个弱引用升级为一个强引用。不管是sp还是wp,实际上都是android利用现有的c++特性来解决内存使用和回收的一种手段。

文二:

转自:http://blog.chinaunix.net/u3/90973/showart_2163813.html

sp和wp的实现过程

个人觉得sp和wp实际上就是android 为其c++实现的自动垃圾 回收机制 ,具体到内部实现,sp和wp实际上只是一个实现垃圾回收功能的接口而已,比如说对*,->的重载,是为了其看起来跟真正的指针一样,而真正实现垃圾回收的是refbase这个基类。这部分代码的目录在:/frameworks/base/include/utils/RefBase.h
首先所有的类都会虚继承refbase类,因为它实现了达到垃圾回收所需要的所有function,因此实际上所有的对象声明出来以后都具备了自动释放自己的能力,也就是说实际上智能指针就是我们的对象本身,它会维持一个对本身强引用和弱引用的计数,一旦强引用计数为0它就会释放掉自己。
首先我们看sp,sp实际上不是smart pointer的缩写,而是strong pointer,它实际上内部就包含了一个指向对象的指针而已。我们可以简单看看sp的一个构造函数:
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
{
if (other) other->incStrong(this);
}
比如说我们声明一个对象:
sp<CameraHardwareInterface> hardware(new CameraHal());
实际上sp指针对本身没有进行什么操作,就是一个指针的赋值,包含了一个指向对象的指针,但是对象会对对象本身增加一个强引用计数,这个 incStrong的实现就在refbase类里面。新new出来一个CameraHal对象,将它的值给 sp<CameraHardwareInterface>的时候,它的强引用计数就会从0变为1。因此每次将对象赋值给一个sp指针的时候,对象的强引用计数都会加1,下面我们再看看sp的析构函数:
template<typename T>
sp<T>::~sp()
{
if (m_ptr) m_ptr->decStrong(this);
}
实际上每次delete一个sp对象的时候,sp指针指向的对象的强引用计数就会减一,当对象的强引用技术 为0的时候这个对象就会被自动释放掉。
wp就是weak pointer的缩写,wp 这个指针类,实际上他是一个弱引用类型的指针类,弱引用是在.net 以及java 中经常用到的,弱引用是一个对象引用的持有者,使用弱引用后可以维持对对象的引用,但是不会阻止其被垃圾回收。如果一个对象只有弱引用了,那它就成为被垃圾回收的候选对象,就像没有剩余的引用一样,而且一旦对象被删除,所有的弱引用也会被清楚。弱引用适合那些数据 成员特别多,而且重新创建又相对容易的类,也就是俗称的胖子类,建立弱引用可以引用对象,但也不阻止其被垃圾回收,在内存的使用方面取得一定的平衡。

在android 中wp 类里面的promote 函数实际上就是将一个弱引用升级为一个强引用。不管是sp 还是wp ,实际上都是android 利用现有的c++ 特性来解决内存使用和回收的一种手段。

,就是为了减少对那些胖子对象对内存的占用,我们首先来看wp的一个构造函数:
wp<T>::wp(T* other)
: m_ptr(other)
{
if (other) m_refs = other->createWeak(this);
}
它和sp一样实际上也就是仅仅对指针进行了赋值而已,对象本身会增加一个对自身的弱引用计数,同时wp还包含一个m_ref指针,这个指针主要是用来将wp升级为sp时候使用的:
template<typename T>
sp<T> wp<T>::promote() const
{
return sp<T>(m_ptr, m_refs);
}
template<typename T>
sp<T>::sp(T* p, weakref_type* refs)
: m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)
{
}
实际上我们对wp指针唯一能做的就是将wp指针升级为一个sp指针,然后判断是否升级成功,如果成功说明对象依旧存在,如果失败说明对象已经被释放掉了。wp指针我现在看到的是在单例中使用很多,确保mhardware对象只有一个,比如:
wp<CameraHardwareInterface> CameraHardwareStub::singleton;
sp<CameraHardwareInterface> CameraHal::createInstance()
{
LOG_FUNCTION_NAME
if (singleton != 0) {
sp<CameraHardwareInterface> hardware = singleton.promote();
if (hardware != 0) {
return hardware;
}
}
sp<CameraHardwareInterface> hardware(new CameraHal()); //强引用加1
singleton = hardware;//弱引用加1
return hardware;//赋值构造函数,强引用加1
}
//hardware被删除,强引用减1

更多相关文章

  1. Android系列之Intent传递对象的两种方法
  2. Android studio插件GsonFormat,返回json快速创建实体对象
  3. Android 智能问答机器人的实现
  4. android将对象写入文件和从文件中读取对象数据
  5. Android可触摸选择刻度,有惯性,指针自动补正的刻度盘/表盘
  6. android 之json对象解析并展示(含json解析源码)
  7. Android中的sp和wp指针

随机推荐

  1. Javascript是实现HTML5强大功能的重要语
  2. 如何使用客户端Javascript数组并通过节点
  3. 小区物业收费管理系统的实习报告
  4. 1. 总是从ID选择器开始继承   在jquery
  5. 小弟初学网页(javascript),看不懂下面的代
  6. 通过jQuery提交的HTML不会接收点击事件
  7. 如何在没有pdf组件的移动浏览器中显示Bas
  8. HTML CSS Javascript中 id重复时会发生的
  9. JavaScript 利用 async await 实现 sleep
  10. js之DOM操作(访问父节点parentNode)