首页 > 代码库 > 解释清楚智能指针一【用自己的话,解释清楚】
解释清楚智能指针一【用自己的话,解释清楚】
写在前面
用自己的话解释清楚~
智能指针是什么,可分为哪几种类型,各有什么特点,解决了什么问题,怎么解决的?
什么是智能指针?
智能指针是C++中的一个概念,主要是通过引用计数的方式,解决动态内存的自动释放问题(类似于Java 、Python中的垃圾回收)。主要解决程序常见的两个问题:动态的申请的内存没有释放;动态申请的内存释放后又被引用。
指针和引用的区别:
指针其实是一个变量,只不过它存储的是另一个变量的内存地址。而引用是另外一个变量的别名,它不占用空间。所以引用定义的时候必须初始化。引用访问对象是直接访问,指针访问对象是间接访问。
他们在源码中的位置
http://androidxref.com/4.4.3_r1.1/xref/frameworks/rs/cpp/util/RefBase.h
http://androidxref.com/4.4.3_r1.1/xref/frameworks/rs/server/RefBase.h
http://androidxref.com/4.4.3_r1.1/xref/system/core/libutils/RefBase.cpp
http://androidxref.com/4.4.3_r1.1/xref/system/core/include/utils/RefBase.h
据观察他们的实现,略有差异,不过对外功能是一致的。在此以前两者为例子。
Android 源码中设计了三个智能指针:
轻量化指针(Light Pointer)、强指针(Strong Pointer)和弱指针(Weak Pointer)。
各指针的特点
强指针:
它会记录对它所指对象的引用次数,当引用次数为0时,自动释放该内存。
弱指针:
它会保存所指向对象的地址。但要引用该对象时,需要先将弱指针升级为强指针,然后再引用。如果该对象已经释放,则升级失败。
轻量级指针源码分析:
163template <class T>
164class LightRefBase
165{
166public:
167 inline LightRefBase() : mCount(0) { }
168 inline void incStrong(__attribute__((unused)) const void* id) const {
169 __sync_fetch_and_add(&mCount, 1);
170 }
171 inline void decStrong(__attribute__((unused)) const void* id) const {
172 if (__sync_fetch_and_sub(&mCount, 1) == 1) {
173 delete static_cast<const T*>(this);
174 }
175 }
176 //! DEBUGGING ONLY: Get current strong ref count.
177 inline int32_t getStrongCount() const {
178 return mCount;
179 }
180
181 typedef LightRefBase<T> basetype;
182
183protected:
184 inline ~LightRefBase() { }
185
186private:
187 friend class ReferenceMover;
188 inline static void moveReferences(void*, void const*, size_t,
189 const ReferenceConverterBase&) { }
190
191private:
192 mutable volatile int32_t mCount;
193};
备注:
__sync_fetch_and_add()
__sync_fetch_and_sub()
用于增减mCount;
无锁编程函数(参考文章:Multithreaded simple data type access and atomic variables)
__attribute__((unused))
在分析系统代码时注意到有些函数会有添加__attribute__((unused)),
在gcc手册中找到了有关的解释:
unused:This attribute, attached to a function, means that the function is meant to be
possibly unused. GCC will not produce a warning for this function.
======================================================================
used: This attribute, attached to a function, means that code must be emitted for the
function even if it appears that the function is not referenced. This is useful,
for example, when the function is referenced only in inline assembly.
表示该函数或变量可能不使用,这个属性可以避免编译器产生警告信息。
强弱指针源码分析
http://androidxref.com/4.4.3_r1.1/xref/system/core/include/utils/StrongPointer.h
29template<typename T> class wp;
//类似于普通类的声明, 这是一个模板类wp的声明,前面的template<typename T> 说//明它是一个模板类,用到的泛型类型 模板类中以T替代
30
31//------------------------------------------------------------------
32
33#define COMPARE(_op_) \
34inline bool operator _op_ (const sp<T>& o) const { \
35 return m_ptr _op_ o.m_ptr; \
36}
\
37inline bool operator _op_ (const T* o) const { \
38 return m_ptr _op_ o; \
39} \
40template<typename U> \
41inline bool operator _op_ (const sp<U>& o) const { \
42 return m_ptr _op_ o.m_ptr; \
43} \
44template<typename U> \
45inline bool operator _op_ (const U* o) const { \
46 return m_ptr _op_ o; \
47} \
48inline bool operator _op_ (const wp<T>& o) const { \
49 return m_ptr _op_ o.m_ptr; \
50} \
51template<typename U> \
52inline bool operator _op_ (const wp<U>& o) const { \
53 return m_ptr _op_ o.m_ptr; \
54}
55
56//-------------------------------------------------------------------
57
58template<typename T>
59class sp {
60public:
61 inline sp() : m_ptr(0) { }
62
63 sp(T* other);
64 sp(const sp<T>& other);
65 template<typename U> sp(U* other);
66 template<typename U> sp(const sp<U>& other);
67
68 ~sp();
69
70 // Assignment
71
72 sp& operator = (T* other);
73 sp& operator = (const sp<T>& other);
74
75 template<typename U> sp& operator = (const sp<U>& other);
76 template<typename U> sp& operator = (U* other);
77
78 //! Special optimization for use by ProcessState (and nobody else).
79 void force_set(T* other);
80
81 // Reset
82
83 void clear();
84
85 // Accessors
86
87 inline T& operator* () const { return *m_ptr; }
88 inline T* operator-> () const { return m_ptr; }
89 inline T* get() const { return m_ptr; }
90
91 // Operators
92
93 COMPARE(==)
94 COMPARE(!=)
95 COMPARE(>)
96 COMPARE(<)
97 COMPARE(<=)
98 COMPARE(>=)
99
100private:
101 template<typename Y> friend class sp;
102 template<typename Y> friend class wp;
103 void set_pointer(T* ptr);
104 T* m_ptr;
105};
106
107#undef COMPARE
109//------------------------------------------------------------------
110// No user serviceable parts below here.
111
112template<typename T>
113sp<T>::sp(T* other)
114 : m_ptr(other) {
115 if (other)
116 other->incStrong(this);
117}
118
119template<typename T>
120sp<T>::sp(const sp<T>& other)
121 : m_ptr(other.m_ptr) {
122 if (m_ptr)
123 m_ptr->incStrong(this);
124}
125
126template<typename T> template<typename U>
127sp<T>::sp(U* other)
128 : m_ptr(other) {
129 if (other)
130 ((T*) other)->incStrong(this);
131}
132
133template<typename T> template<typename U>
134sp<T>::sp(const sp<U>& other)
135 : m_ptr(other.m_ptr) {
136 if (m_ptr)
137 m_ptr->incStrong(this);
138}
139
140template<typename T>
141sp<T>::~sp() {
142 if (m_ptr)
143 m_ptr->decStrong(this);
144}
145
146template<typename T>
147sp<T>& sp<T>::operator =(const sp<T>& other) {
148 T* otherPtr(other.m_ptr);
149 if (otherPtr)
150 otherPtr->incStrong(this);
151 if (m_ptr)
152 m_ptr->decStrong(this);
153 m_ptr = otherPtr;
154 return *this;
155}
156
157template<typename T>
158sp<T>& sp<T>::operator =(T* other) {
159 if (other)
160 other->incStrong(this);
161 if (m_ptr)
162 m_ptr->decStrong(this);
163 m_ptr = other;
164 return *this;
165}
166
167template<typename T> template<typename U>
168sp<T>& sp<T>::operator =(const sp<U>& other) {
169 T* otherPtr(other.m_ptr);
170 if (otherPtr)
171 otherPtr->incStrong(this);
172 if (m_ptr)
173 m_ptr->decStrong(this);
174 m_ptr = otherPtr;
175 return *this;
176}
177
178template<typename T> template<typename U>
179sp<T>& sp<T>::operator =(U* other) {
180 if (other)
181 ((T*) other)->incStrong(this);
182 if (m_ptr)
183 m_ptr->decStrong(this);
184 m_ptr = other;
185 return *this;
186}
187
188template<typename T>
189void sp<T>::force_set(T* other) {
190 other->forceIncStrong(this);
191 m_ptr = other;
192}
193
194template<typename T>
195void sp<T>::clear() {
196 if (m_ptr) {
197 m_ptr->decStrong(this);
198 m_ptr = 0;
199 }
200}
201
202template<typename T>
203void sp<T>::set_pointer(T* ptr) {
204 m_ptr = ptr;
205}
206
207}; // namespace android
208
209//----------------------------------------------------------------
Sp中可使用decStrong()等函数,是由于所有项使用强指针sp的类必须继承自RefBase类(decStrong()等函数 是RefBase类的成员函数)。
100private:
101 template<typename Y> friend class sp;
对这段代码的理解:
先说明一下友元类的作用
C++的设计中类的出现是为了提高程序的独立性和封装性。类中使用了关键字public 和private来定义了类中成员的访问权限,一般情况下,非类成员函数式不能访问类的内部成员函数或变量的。
但,有些情况可能需要这样,所以出C++的设计者设计了友元类这个类与类之间的关系,
它的特点是
- 是一个单向的关系,即定义了B是A的友元类,并不代表A是B的友元;
- 不具备传递性
这段代码中定义类模板类sp是模板类sp的友元类,是为了可以访问传递进来的其他类型的模板类sp的对象的私有成员变量(这里主要是m_ptr)。
比如重载的操作符==
40template<typename U> \
41inline bool operator _op_ (const sp<U>& o) const { \
42 return m_ptr _op_ o.m_ptr;
如果没有定义为友元类,就不能访问传递进来的 对象o的私有变量o.m_ptr。
QQ群 计算机科学与艺术 272583193
加群链接:http://jq.qq.com/?_wv=1027&k=Q9OxMv