爲什麼會引入智能指針?——彌補C++代碼的指針問題。這是主要目的。
智能指針是一種能夠自動維護對象引用計數的技術。智能指針本身並不是指針,它是一個對象,但是它引用了一個世紀使用的對象。因爲它是一個對象,所以它可以自動地維護實際對象的引用技術——在智能指針構造時,增加它對所引用的對象的引用計數;在智能指針析構時,就減少它所引用的對象的引用計數。由於智能指針的構造和析構都是自動的,所以就自動地實現了對象的引用計數。
爲了解決相互引用死鎖導致兩個對象不能被釋放的問題,引入了強制針和弱指針。
android系統引入了三種智能指針類型:輕量級指針(Light Pointer)、強指針(Strong Pointer)和弱指針(Weak Pointer)。
一個對象的弱引用計數一定是大於或者是等於它的強引用計數。
弱指針和強指針最大的區別是:弱指針不可以直接操作它所引用的對象。因爲它所引用的對象可能是不受弱引用計數控制的,即它所引用的對象可能是一個無效的對象。因此,如果需要操作一個弱指針所引用的對象,那麼就需要將這個弱指針升級爲強指針,通過成員函數promote來實現的。如果升級成功,就說明該弱指針所引用的對象還沒有被銷燬,還可以正常使用。
輕量級指針的原始基類是LightRefBase。
// ---------------------------------------------------------------------------
template <class T>
class LightRefBase
{
public:
inline LightRefBase() : mCount(0) { }
inline void incStrong(const void* id) const {
android_atomic_inc(&mCount);
}
inline void decStrong(const void* id) const {
if (android_atomic_dec(&mCount) == 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* d, void const* s, size_t n,
const ReferenceConverterBase& caster) { }
private:
mutable volatile int32_t mCount;
};
強指針和弱指針的原始基類是RefBase.
// ---------------------------------------------------------------------------
class RefBase
{
public:
void incStrong(const void* id) const;
void decStrong(const void* id) const;
void forceIncStrong(const void* id) const;
//! DEBUGGING ONLY: Get current strong ref count.
int32_t getStrongCount() const;
class weakref_type
{
public:
RefBase* refBase() const;
void incWeak(const void* id);
void decWeak(const void* id);
// acquires a strong reference if there is already one.
bool attemptIncStrong(const void* id);
// acquires a weak reference if there is already one.
// This is not always safe. see ProcessState.cpp and BpBinder.cpp
// for proper use.
bool attemptIncWeak(const void* id);
//! DEBUGGING ONLY: Get current weak ref count.
int32_t getWeakCount() const;
//! DEBUGGING ONLY: Print references held on object.
void printRefs() const;
//! DEBUGGING ONLY: Enable tracking for this object.
// enable -- enable/disable tracking
// retain -- when tracking is enable, if true, then we save a stack trace
// for each reference and dereference; when retain == false, we
// match up references and dereferences and keep only the
// outstanding ones.
void trackMe(bool enable, bool retain);
};
weakref_type* createWeak(const void* id) const;
weakref_type* getWeakRefs() const;
//! DEBUGGING ONLY: Print references held on object.
inline void printRefs() const { getWeakRefs()->printRefs(); }
//! DEBUGGING ONLY: Enable tracking of object.
inline void trackMe(bool enable, bool retain)
{
getWeakRefs()->trackMe(enable, retain);
}
typedef RefBase basetype;
protected:
RefBase();
virtual ~RefBase();
//! Flags for extendObjectLifetime()
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
void extendObjectLifetime(int32_t mode);
//! Flags for onIncStrongAttempted()
enum {
FIRST_INC_STRONG = 0x0001
};
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
virtual void onLastWeakRef(const void* id);
private:
friend class ReferenceMover;
static void moveReferences(void* d, void const* s, size_t n,
const ReferenceConverterBase& caster);
private:
friend class weakref_type;
class weakref_impl;
RefBase(const RefBase& o);
RefBase& operator=(const RefBase& o);
weakref_impl* const mRefs; //真正用來描述對象的引用計數的
};
weakref_impl類繼承於weakref_type類。
// ---------------------------------------------------------------------------
class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
volatile int32_t mStrong; //對象的強引用計數
volatile int32_t mWeak; //對象的弱引用計數
RefBase* const mBase; //所引用對象的地址
volatile int32_t mFlags; //標誌值:描述對象的生命週期控制方式
//mFlags取值範圍:OBJECT_LIFETIME_STRONG、 OBJECT_LIFETIME_WEAK、OBJECT_LIFETIME_MASK
//OBJECT_LIFETIME_STRONG:表示對象的生命週期只受強引用計數影響
//OBJECT_LIFETIME_WEAK:表示對象的生命週期同時受強引用計數和弱引用計數影響
//OBJECT_LIFETIME_MASK:表示對象的生命週期完全不受強引用計數或者弱引用計數的影響,迴歸到C++本身
#if !DEBUG_REFS
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)
, mFlags(0)
{
}
void addStrongRef(const void* /*id*/) { }
void removeStrongRef(const void* /*id*/) { }
void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
void addWeakRef(const void* /*id*/) { }
void removeWeakRef(const void* /*id*/) { }
void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
void printRefs() const { }
void trackMe(bool, bool) { }
#else
... ...
#endif
};