天天看點

sp<>和wp<>指針詳細說明

首先我們看sp,sp實際上不是smart pointer的縮寫,而是strong pointer,它實際上内部就包含了一個指向對象的指針而已。

文一:

轉: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

繼續閱讀