智能指標來源
由于android系統底層的很大的一部分是用C++實作的,C++的開發就難免會使用到指標的這個知識 點,而C++的難點和容易出問題的也在于指標,使用指標出錯,常常會引發帶來對專案具有毀滅性的錯誤,記憶體泄漏、邏輯錯誤、系統崩潰,
引發指標錯誤情況表現常常有如下幾個表現情況:
1.申請了記憶體空間,但是忘記釋放指標所指向的物件占用的記憶體空間,
2.使用了無效的指標,
因此在android的C++代碼部分采用了智能指標的技術,智能指標通過一種能夠自動危害物件參考計數的技術,來解決C++中指標存在的缺陷問題,
在android系統中提供了三種型別的C++智能指標,分別為:輕量級智能指標、強指標、弱指標,
下面主要通過進行分析輕量級指標的實作原理,
輕量級指標
輕量級指標就是通過利用簡單的參考計數計數類維護物件的生命周期,如果一個類的物件支持使用輕量級指標,那么它就必須要從LightRefBase類進行繼承,因為這個LightRefBase類提供了一個簡單的參考計數器,
LightRefBase類定義
下面的原始碼主要依據android5.0的原始碼進行分析的,LightRefBase類的定義在android系統中的\frameworks\rs\cpp\util\RefBase.h 這個檔案中,
LightRefBase類也是一個模板類,模板引數T表示物件的實際型別,它必須進行對LightRefBase這個類繼承,
//模板類
template <class T>
class LightRefBase
{
public:
//公共的行內函式
inline LightRefBase() : mCount(0) { }
inline void incStrong(__attribute__((unused)) const void* id) const {
__sync_fetch_and_add(&mCount, 1);
}
inline void decStrong(__attribute__((unused)) const void* id) const {
if (__sync_fetch_and_sub(&mCount, 1) == 1) {
delete static_cast<const T*>(this);
}
}
//! DEBUGGING ONLY: Get current strong ref count.
inline int32_t getStrongCount() const {
return mCount;
}
typedef LightRefBase<T> basetype;
protected:
//行內的虛構函式
inline ~LightRefBase() { }
private:
friend class ReferenceMover;
inline static void moveReferences(void*, void const*, size_t,
const ReferenceConverterBase&) { }
private:
mutable volatile int32_t mCount;
};
上面LightRefBase類定義涉及到幾個知識點:
1、C++的三個訪問權限型別:public、protected、private,
public:可以被任意物體訪問,
protected:只允許子類及本類的成員函式訪問,
private:只允許本類的成員函式訪問,
2、C++中的inline行內函式
在函式第一部分如果包含有inline關鍵字的函式,那么這個函式就表示為行內函式,行內函式主要為了解決一些頻繁呼叫的小函式大量消耗堆疊空間(堆疊記憶體)的問題,
inline的使用是有所限制的,inline只適合涵數體內代碼簡單的涵數使用,不能包含復雜的結構控制陳述句例如while、switch,并且不能行內函式本身不能是直接遞回函式(遞回函式:自己內部還呼叫自己的函式),
3、C++中的friend友元函式
C++中的友元機制允許類的非公有成員被一個類或者函式訪問,友元按型別分為三種:普通非類成員函式作為友元,類的成員函式作為友元,類作為友元,
友元函式是可以直接訪問類的私有成員的非成員函式,它是定義在類外的普通函式,它不屬于任何類,但需要在類的定義中加以宣告,宣告時只需在友元的名稱前加上關鍵字friend,
4、C++中的mutable關鍵字
mutable是為了突破const的限制而設定的,被mutable修飾的變數,將永遠處于可變的狀態,即使在一個const函式中,
5、C++中的template類模板
一個類模板(也稱為類屬類或類生成類)同意用戶為類定義一種模式,使得類中的某些資料成員、默寫成員函式的參數、某些成員函式的回傳值,能夠取隨意型別(包含系統提前定義的和用戶自己定義的),
類模板的應用場景:多個類有著共同操作,但是資料型別不同,
LightRefBase的實作類
輕量級LightRefBase類的實作類為wp類,它也是在\frameworks\rs\cpp\util\RefBase.h 這個檔案中,wp也是一個模板類,模板引數T表示的是物件的實際型別,它必須繼承LightRefBase類,由于wp類也是強指標的實作類,因此我們只需要分析下該wp類中關于輕量級指標類的實作部分就可以了,
//模板類
template <typename T>
class wp
{
public:
typedef typename RefBase::weakref_type weakref_type;
//輕量級指標需要用到的建構式
inline wp() : m_ptr(0) { }
wp(T* other);
wp(const wp<T>& other);
wp(const sp<T>& other);
template<typename U> wp(U* other);
template<typename U> wp(const sp<U>& other);
template<typename U> wp(const wp<U>& other);
//輕量級指標需要用到的虛構函式
~wp();
// Assignment
wp& operator = (T* other);
wp& operator = (const wp<T>& other);
wp& operator = (const sp<T>& other);
template<typename U> wp& operator = (U* other);
template<typename U> wp& operator = (const wp<U>& other);
template<typename U> wp& operator = (const sp<U>& other);
void set_object_and_refs(T* other, weakref_type* refs);
// promotion to sp
sp<T> promote() const;
// Reset
void clear();
// Accessors
inline weakref_type* get_refs() const { return m_refs; }
inline T* unsafe_get() const { return m_ptr; }
// Operators
COMPARE_WEAK(==)
COMPARE_WEAK(!=)
COMPARE_WEAK(>)
COMPARE_WEAK(<)
COMPARE_WEAK(<=)
COMPARE_WEAK(>=)
inline bool operator == (const wp<T>& o) const {
return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
}
template<typename U>
inline bool operator == (const wp<U>& o) const {
return m_ptr == o.m_ptr;
}
inline bool operator > (const wp<T>& o) const {
return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
}
template<typename U>
inline bool operator > (const wp<U>& o) const {
return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
}
inline bool operator < (const wp<T>& o) const {
return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
}
template<typename U>
inline bool operator < (const wp<U>& o) const {
return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
}
inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
//輕量級指標會用到的變數m_ptr
T* m_ptr;
weakref_type* m_refs;
};
總結
通過前面的概念和系統原始碼實作功能原理分析,我們如果要使用輕量級指標的話,那么要包含頭檔案并采用繼承LightRefBase類的方式,那么就可以使用輕量級指標的功能了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/306018.html
標籤:其他
上一篇:作業中常用的前端知識總結
