android智能指針

下面是android 7.1.1中的源碼
先從簡單的LightRefBase開始, 它里面只用了簡單的mCount來計數(shù).

## LightRefBase

template <class T>
class LightRefBase
{
    public:
    inline LightRefBase() : mCount(0) { }
    //計數(shù)+1
    inline void incStrong(__attribute__((unused)) const void* id) const {
        mCount.fetch_add(1, std::memory_order_relaxed);
    }
    inline void decStrong(__attribute__((unused)) const void* id) const {
    //計數(shù)-1, 返回減1之前的值
       if (mCount.fetch_sub(1, std::memory_order_release) == 1) {
            std::atomic_thread_fence(std::memory_order_acquire);
            delete static_cast<const T*>(this); //如果減掉后引用計數(shù)為0, 刪掉該引用
        }
}
    inline int32_t getStrongCount() const {
        return mCount.load(std::memory_order_relaxed);
    }
    private:
    mutable std::atomic<int32_t> mCount;
};
int main(int argc, char** argv)
{
    //自定義LightClass 繼承LightRefBase
    LightClass* pLightClass = new LightClass();
    //調(diào)用① sp的一個參數(shù)的構(gòu)造函數(shù)
    sp<LightClass> lpOut = pLightClass;
    //pLightClass 引用計數(shù)+1, 所以下面輸出 1
    printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());
 
    {
        //調(diào)用② sp的另一個構(gòu)造函數(shù)
        sp<LightClass> lpInner = lpOut;
        //上面pLight的引用計數(shù)+1, 所以這里輸出2
        printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());
    }
    //上面作用域結(jié)束所以, lpInner調(diào)用析構(gòu)函數(shù)③
    //pLightClass引用計數(shù)-1, 這里輸出 1
    printf("Light Ref Count: %d.\n", pLightClass->getStrongCount());
 
    return 0;            
}

//StrongPointer.h
//① 
template<typename T>
sp<T>::sp(T* other) //other在上面的例子為pLightClass
        : m_ptr(other) {
    if (other)
        //調(diào)用LightRefBase的incStrong, LightRefBase的mCount+1;
        other->incStrong(this);
}
//②
template<typename T>
sp<T>::sp(const sp<T>& other) //other參數(shù)在上面的例子中為lpOut
        : m_ptr(other.m_ptr) { //other.m_ptr為 pLightClass, m_ptr其實就是pLightClass的引用
    if (m_ptr)
        m_ptr->incStrong(this); //引用計數(shù)+1
}
//③
template<typename T>
sp<T>::~sp() {
    if (m_ptr) //m_ptr為pLightClass的引用
        m_ptr->decStrong(this);
}

## RefBase

# RefBase原型
//RefBase.h
class RefBase
{
    private:
        //weakref_impl為RefBase的內(nèi)部類weakref_type的實現(xiàn)類, 
        //mRefs包含強引用計數(shù), 弱引用計數(shù), flag, 以及指向外部類RefBase的指針mBase
        weakref_impl* const mRefs;  
    protected:
        RefBase(); //構(gòu)造函數(shù)中 new weakref_impl()
        virtual ~RefBase(); //析構(gòu)做了較多工作
        //! Flags for extendObjectLifetime()
        enum { //沒有了forever
            OBJECT_LIFETIME_STRONG  = 0x0000, //對象受強引用控制, 默認
            OBJECT_LIFETIME_WEAK    = 0x0001, //對象受弱引用控制
            OBJECT_LIFETIME_MASK    = 0x0001
        };
    public:
        void incStrong(const void* id) const;
        void decStrong(const void* id) const;
        weakref_type*   createWeak(const void* id) const;
    //...省略
}

上面是RefBase中的幾個重要函數(shù)聲明, 接下來是weakref_impl的聲明

# weakref_type, weakref_impl原型
//RefBase.h
class weakref_type
{
public:
    void incWeak(const void* id);
    void decWeak(const void* id);
    bool attemptIncStrong(const void* id);
    //..省略
}
//RefBase.cpp
class RefBase::weakref_impl : public RefBase::weakref_type //weakref_type定義了幾個函數(shù)
{
public:
    std::atomic<int32_t>    mStrong; //強引用計數(shù)
    std::atomic<int32_t>    mWeak;   //弱引用計數(shù)
    RefBase* const          mBase;   //引用外部指針
    std::atomic<int32_t>    mFlags;  //標(biāo)記
    //..省略空方法
}

后面都是控制weakref_impl對象, 這里只要記住有四個變量, 和加減引用計數(shù)的方法, 接下來先看下它們的實現(xiàn)

# weakref_type, weakref_impl實現(xiàn)
//RefBase.cpp
weakref_impl(RefBase* base)
    : mStrong(INITIAL_STRONG_VALUE) //強引用計數(shù)默認值
    , mWeak(0)  //弱引用計數(shù)0
    , mBase(base) //引用外部對象 RefBase
    , mFlags(0){} //flag默認0, 表示受強引用控制
void RefBase::weakref_type::incWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->addWeakRef(id); //空方法
    const int32_t c __unused = impl->mWeak.fetch_add(1, //弱引用計數(shù)+1
            std::memory_order_relaxed);
}
void RefBase::weakref_type::decWeak(const void* id)
{
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id); //空方法
    const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release); //弱引用-1
    if (c != 1) return; //減1后弱引用計數(shù)不為0, 直接返回
    //弱引用計數(shù)為0, 接著往下執(zhí)行
    //弱引用計數(shù)>=強引用計數(shù)
    atomic_thread_fence(std::memory_order_acquire);
    int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
    if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) { 
        // 受強引用計數(shù)影響, 默認
        if (impl->mStrong.load(std::memory_order_relaxed)
                == INITIAL_STRONG_VALUE) {
            //如果強引用計數(shù)為初始值, 回收RefBase
            delete impl->mBase;
        } else {
            //強引用計數(shù)為0, 回收weakref_impl
            delete impl;
        }
    } else {
        // 受弱引用計數(shù)控制, 回收RefBase
        impl->mBase->onLastWeakRef(id);
        delete impl->mBase;
    }
}

bool RefBase::weakref_type::attemptIncStrong(const void* id)
{
    //該方法是, 弱引用變?yōu)閺娨? 所以強引用計數(shù)+1, 弱引用計數(shù)也需要+1
    //這里弱引用計數(shù)先+1, 如果變?yōu)閺娨檬? 則再-1
    incWeak(id);
    
    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    int32_t curCount = impl->mStrong.load(std::memory_order_relaxed);
    
    //下面判斷成立, 說明已經(jīng)有強引用, 說明可以, 升級為強引用
    //while為了解決多線程的問題
    while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
        if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                std::memory_order_relaxed)) {
            break;
        }
    }
    
    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
        // 兩種情況
        // - 沒有過強引用
        // - 或者強引用都被回收了
        int32_t flags = impl->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            // 默認受強引用控制時
            // 當(dāng)最后的強引用被釋放了, 所以curCount<=0
            if (curCount <= 0) {
                // 強引用<=0 肯定是從1減到了0, 根據(jù)decStrong()方法, 受強引用控制時, 釋放RefBase
                // 所以不能升級為強引用
                decWeak(id); //弱引用計數(shù)-1, 因為上面加過1
                return false;
            }

            //curCount為初始值, 說明沒有過強引用, 可以嘗試一下
            while (curCount > 0) {
                //mStrong + 1
                if (impl->mStrong.compare_exchange_weak(curCount, curCount+1,
                        std::memory_order_relaxed)) {
                    break;
                }
            }
            if (curCount <= 0) {
                // 其他線程破壞了這次的升級, promote()失敗
                decWeak(id);
                return false;
            }
        } else {
            // 受弱引用控制
            // onIncStrongAttempted()默認為true, 但是可以重寫該方法
            // 能否promote()成功取決于開發(fā)者.
            if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
                decWeak(id);
                return false;
            }
            // 可以升級為強引用, 強引用計數(shù)+1
            curCount = impl->mStrong.fetch_add(1, std::memory_order_relaxed);
            // 多線程問題, 別的線程動了強引用計數(shù)
            if (curCount != 0 && curCount != INITIAL_STRONG_VALUE) {
                impl->mBase->onLastStrongRef(id);
            }
        }
    }
    impl->addStrongRef(id);// 空方法
    // 修正強引用計數(shù)為1
    if (curCount == INITIAL_STRONG_VALUE) {
        impl->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
                std::memory_order_relaxed);
    }

    return true;
}
# RefBase實現(xiàn)
//RefBase.cpp
RefBase::RefBase() //無參構(gòu)造函數(shù)
    : mRefs(new weakref_impl(this)){}
RefBase::~RefBase() //析構(gòu)函數(shù)
{
    if (mRefs->mStrong.load(std::memory_order_relaxed)
            == INITIAL_STRONG_VALUE) {
        //沒有用過強引用, 刪除weakref_impl
        delete mRefs;
    } else {
        int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
        if ((flags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
            if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
                //受弱引用控制, 并且若引用計數(shù) = 0, 刪除weakref_impl
                delete mRefs;
            }
        }
    }
    // for debugging purposes, clear this.
    const_cast<weakref_impl*&>(mRefs) = NULL;
}

//wp中需要調(diào)用
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
    mRefs->incWeak(id);
    return mRefs;
}
//incStrong
  void RefBase::incStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->incWeak(id); //弱引用計數(shù)+1
    refs->addStrongRef(id); //空方法
    //強引用+1
    const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
    if (c != INITIAL_STRONG_VALUE)  {
        return;
    }
    //強引用默認值為1<<28, 減去1<<28, 現(xiàn)在值為1
    int32_t old = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
            std::memory_order_relaxed);
    refs->mBase->onFirstRef();
}
  void RefBase::decStrong(const void* id) const
{
    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id);//空方法
    //強引用-1
    const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);
    if (c == 1) { //減去后強引用計數(shù) = 0
        std::atomic_thread_fence(std::memory_order_acquire);
        refs->mBase->onLastStrongRef(id);//可繼承
        int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
        if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
            //受強引用計數(shù)控制, 默認, 刪掉RefBase, 并且調(diào)用RefBase的析構(gòu)函數(shù)
            delete this;
        }
    }
    refs->decWeak(id);
}
  • RefBase::RefBase()

    new weakref_impl(), weakref_impl初始化

  • RefBase::~RefBase()

    強引用計數(shù)為初始值 || (受弱引用控制&&弱引用計數(shù)==0) -> 刪掉weakref_impl

  • RefBase::incStrong()

    調(diào)用 weakref_type::incWeak (弱引用+1)

    強引用+1(如果第一次加1, 那么減掉初始值, 最終為1),

  • RefBase::decStrong()

    強引用-1, 減去后如果強引用計數(shù)為0, 并且受強引用控制, 釋放RefBase(實際對象)

    調(diào)用 weakref_type::decWeak (弱引用-1, 還有其他邏輯)

  • RefBase::weakref_type::incWeak()

    強引用+1

  • RefBase::weakref_type::decWeak()

    弱引用-1, 減去后如果弱引用計數(shù)為0, 分兩種情況, 受強引用控制, 受弱引用控制

    其實弱引用計數(shù)為0, 不管受強引用還是弱引用控制, RefBase和weakref_impl都需要釋放, 下面的判斷是為了不重復(fù)釋放

    1. 受強引用控制, 強引用計數(shù)為初始值, 釋放RefBase, 不為初始值, 釋放weakref_impl

      1. 強引用計數(shù)為初始值, 釋放RefBase, RefBase調(diào)用析構(gòu)函數(shù), 釋放weakref_impl

      2. 強引用計數(shù)不為初始值說明, 調(diào)用過decStrong(), 并且受強引用控制, 所以會釋放RefBase, 這里只需再釋放weakref_impl就可以了

    2. 受弱引用控制, 釋放RefBase

      受弱引用控制, 釋放RefBase, RefBase調(diào)用析構(gòu)函數(shù), 釋放weakref_impl

  • RefBase::weakref_type::attemptIncStrong()

    不考慮多線程的情況下, 首先如果已經(jīng)有強引用, 那么可以直接升級強引用.

    當(dāng)強引用<=0, 或者沒有初始化過強引用時分兩種情況, 受強引用或者弱引用控制

    1. 受強引用控制

      1. 強引用<=0, 說明RefBase已經(jīng)被釋放了, 升級失敗

      2. 強引用為默認值, 說明沒有過強引用, 可以升級

    2. 受弱引用控制

      首先判斷開發(fā)者是否希望可以升級, 默認為true, 升級OK

RefBase的重要函數(shù)都說明完了, 接下來是strong pointer和 weak pointer, 如果上面的RefBase弄明白了, sp和wp就很簡單, 只要關(guān)注它們的構(gòu)造函數(shù)和析構(gòu)函數(shù), 加上wp的promote()函數(shù)即可.

## sp和wp

# sp實現(xiàn)
//StrongPointer.h
template<typename T>
class sp {
public:
    inline sp() : m_ptr(0) { }
    
    //構(gòu)造方法很多, 其他也都一樣調(diào)用RefBase的incStrong()函數(shù)
    template<typename T>
    sp<T>::sp(const sp<T>& other)
        : m_ptr(other.m_ptr) {
        if (m_ptr)
            m_ptr->incStrong(this);
    }
        
    //析構(gòu)函數(shù)
    template<typename T>
    sp<T>::~sp() {
        if (m_ptr)
            m_ptr->decStrong(this);
    }
    
  
    // 特殊! 用于ProcessState, 不關(guān)注
    void force_set(T* other);
  
    // 操作符重載 sp可以自由使用引用對象
    inline  T&      operator* () const  { return *m_ptr; }
    inline  T*      operator-> () const { return m_ptr;  }
    inline  T*      get() const         { return m_ptr; }
    
    // 也是為了 sp自由使用引用對象, 宏定義就不貼了
    COMPARE(==)
    COMPARE(!=)
    COMPARE(>)
    COMPARE(<)
    COMPARE(<=)
    COMPARE(>=)

private:    
    template<typename Y> friend class sp;
    template<typename Y> friend class wp;
    void set_pointer(T* ptr) { m_ptr = ptr; }
    T* m_ptr; //引用對象
};

這里只需明白3點:

  1. 構(gòu)造函數(shù)調(diào)用 incStrong(), 強引用+1, 弱引用+1
  2. 析構(gòu)函數(shù)調(diào)用 decStrong(), 強引用-1, 弱引用-1 (還有其他一些邏輯)
  3. sp可以自由操作引用對象
# wp實現(xiàn)
//RefBase.h
template <typename T>
class wp
{
public:
template<typename T> //構(gòu)造函數(shù)
    wp<T>::wp(T* other): m_ptr(other)
    {
        //createWeak()方法很簡單, 上面有實現(xiàn), 只是調(diào)用下incWeak, 返回weakref_impl對象      
        if (other) m_refs = other->createWeak(this);
    }
template<typename T> //析構(gòu)函數(shù)
    wp<T>::~wp()
    {
        if (m_ptr) m_refs->decWeak(this);
    }
template<typename T>
    sp<T> wp<T>::promote() const //重點方法, wp升級sp
    {
        sp<T> result;
        if (m_ptr && m_refs->attemptIncStrong(&result)) {
        result.set_pointer(m_ptr);
    }
    return result; //如果升級失敗, 引用對象為空
}  
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
T*              m_ptr; //引用對象
weakref_type*   m_refs; //RefBase中的weakref_impl, 因為要調(diào)用weakref_impl的方法
};

wp的要明白4點:

  1. 構(gòu)造函數(shù)調(diào)用 createWeak(), 弱引用+1
  2. 析構(gòu)函數(shù)調(diào)用 decWeak() 弱引用-1 (還有其他一些邏輯)
  3. wp不可以自由操作引用對象
  4. wp的promote()方法, 可以升級為sp, 但是如果升級失敗sp的引用對象為空, 所以需要做判斷

OK, 智能指針的基本方法都已經(jīng)講清楚, 這里用老羅的例子實踐一下.

class WeightClass : public RefBase
{
public:
    void printRefCount()
    {
        int32_t strong = getStrongCount();
        weakref_type* ref = getWeakRefs();
        printf("-----------------------\n");
        printf("Strong Ref Count: %d.\n", strong); //打印強引用計數(shù)
        printf("Weak Ref Count: %d.\n", ref->getWeakCount()); //打印弱引用計數(shù)
        printf("-----------------------\n");
    }
};

class StrongClass : public WeightClass
{
public:
    StrongClass()
    {
        printf("Construct StrongClass Object.\n");
    }
    
    virtual ~StrongClass()
    {
        printf("Destory StrongClass Object.\n");
    }
};

class WeakClass : public WeightClass
{
public:
    WeakClass()
    {
        extendObjectLifetime(OBJECT_LIFETIME_WEAK); //受弱引用控制
        printf("Construct WeakClass Object.\n");
    }
    
    virtual ~WeakClass()
    {
        printf("Destory WeakClass Object.\n");
    }
};

void TestStrongClass(StrongClass* pStrongClass)
{
    wp<StrongClass> wpOut = pStrongClass; //弱引用計數(shù) +1
    pStrongClass->printRefCount();
    
    {
        sp<StrongClass> spInner = pStrongClass; //強引用計數(shù)+1, 弱引用計數(shù)+1
        pStrongClass->printRefCount();
    }//調(diào)用sp的析構(gòu)函數(shù), 強引用 = 0, 弱引用 = 1, 因受強引用控制, 所以對象被刪除
    
    sp<StrongClass> spOut = wpOut.promote(); //升級失敗
    printf("spOut: %p.\n", spOut.get());
}

void TestWeakClass(WeakClass* pWeakClass)
{
    wp<WeakClass> wpOut = pWeakClass; //弱引用計數(shù) +1
    pWeakClass->printRefCount();
    
    {
        sp<WeakClass> spInner = pWeakClass; //強引用計數(shù)+1, 弱引用計數(shù)+1
        pWeakClass->printRefCount();
    }//調(diào)用sp的析構(gòu)函數(shù), 強引用 = 0, 弱引用 = 1, 因受弱引用控制, 所以對象不會被刪除
    
    pWeakClass->printRefCount();
    sp<WeakClass> spOut = wpOut.promote(); //升級成功
    printf("spOut: %p.\n", spOut.get());
}

int main(int argc, const char * argv[]) {
    
    printf("Test Strong Class: \n");
    StrongClass* pStrongClass = new StrongClass();
    TestStrongClass(pStrongClass);
    
    printf("\nTest Weak Class: \n");
    WeakClass* pWeakClass = new WeakClass();
    TestWeakClass(pWeakClass);

    return 0;
}
//輸出:
/*
Test Strong Class: 
Construct StrongClass Object.
-----------------------
Strong Ref Count: 268435456.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
Destory StrongClass Object.
spOut: 0x0.


Test Weak Class: 
Construct WeakClass Object.
-----------------------
Strong Ref Count: 268435456.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
spOut: 0x100300060.
Destory WeakClass Object.
*/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嫉沽,一起剝皮案震驚了整個濱河市苍鲜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖捻脖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件可帽,死亡現(xiàn)場離奇詭異橘茉,居然都是意外死亡除嘹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門又碌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來九昧,“玉大人,你說我怎么就攤上這事毕匀≈ィ” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵皂岔,是天一觀的道長蹋笼。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么剖毯? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任圾笨,我火速辦了婚禮,結(jié)果婚禮上逊谋,老公的妹妹穿的比我還像新娘擂达。我一直安慰自己,他們只是感情好胶滋,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布板鬓。 她就那樣靜靜地躺著,像睡著了一般究恤。 火紅的嫁衣襯著肌膚如雪穗熬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天丁溅,我揣著相機與錄音,去河邊找鬼探遵。 笑死窟赏,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的箱季。 我是一名探鬼主播涯穷,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼藏雏!你這毒婦竟也來了拷况?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤掘殴,失蹤者是張志新(化名)和其女友劉穎赚瘦,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奏寨,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡起意,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了病瞳。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片揽咕。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖套菜,靈堂內(nèi)的尸體忽然破棺而出亲善,到底是詐尸還是另有隱情,我是刑警寧澤逗柴,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布蛹头,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏掘而。R本人自食惡果不足惜挟冠,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望袍睡。 院中可真熱鬧知染,春花似錦、人聲如沸斑胜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽止潘。三九已至掺炭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間凭戴,已是汗流浹背涧狮。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留么夫,地道東北人者冤。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像档痪,于是被迫代替她去往敵國和親涉枫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 前言 Java 和 C/C++ 的一個重大區(qū)別腐螟,就是它沒有"指針"的概念愿汰,這并不代表 Java 不需要只用指針,而...
    seraphzxz閱讀 2,489評論 0 54
  • 指針 在傳統(tǒng)的C++編程中乐纸,指針的使用一直是一把雙刃劍衬廷。指針賦予了我們直接操作硬件地址的能力,但同時也帶來了諸多問...
    passerbywhu閱讀 2,867評論 0 2
  • 引言:由于未來需要深入android底層進行系統(tǒng)級別的開發(fā)锯仪,所以最近在看老羅的《Android系統(tǒng)源代碼情景分析》...
    拿破輪閱讀 2,212評論 0 9
  • 移步系列Android跨進程通信IPC系列 Java和C/C++的一個重大區(qū)別泵督,就是它沒有"指針"的概念,這并不代...
    凱玲之戀閱讀 1,056評論 0 0
  • Java和C/C++的一個重大區(qū)別庶喜,就是它沒有"指針"的概念小腊,這并不代表Java不需要指針,而是將這個"超級武器隱...
    Sophia_dd35閱讀 526評論 0 1