Liu Hao
Blog: Http://blog.csdn.net/liuhaoyutz
Android version: 4.4.2
In the C + + language, pointer manipulation is the easiest place to do things, and there are several common pointer manipulation errors:
1. Defines a pointer, but does not initialize it. In this case, the pointer points to a random address, where the pointer is used and an unpredictable error occurs. When a pointer is generally defined, the pointer should be initialized at the same time.
2. After an object is new, forget to delete the object. This can cause memory leaks, which can occur over time and repeatedly, and may cause system downtime.
3, wild hands. For example, we new an object A, and with the pointer P1 point to a, after use, we delete Object A, at this point, P1 still points to a original address, but a is deleted, the address is an illegal address. Such a p1 is a wild pointer. For one more example, p1 and P2 two pointers point to a, we set the P1 to null after we delete a through the P1 pointer, but P2 still points to a original address, where P2 is the wild pointer.
To avoid using the above C + + pointers incorrectly, Android provides us with smart pointers, defined in the RefBase.h and StrongPointer.h files in the Frameworks/rs/cpp/util directory.
Android smart pointer is a template class, also divided into strong pointer sp and weak pointer WP. The strong pointer SP is defined as follows:
62template<typename t> 63class sp 64{65public:66 Inline sp (): m_ptr (0) {} n. sp (t* Other); NST sp<t>& Other); Template<typename u> sp (u* Other); Template<typename u> sp (constsp<u>& Other); ~SP (); Assignment//sp& operator = (t* other); sp& operator = (const sp<t>&other); Template<typename u> sp& operator= (const sp<u>& Other); Bayi template<typename u> sp& operator= (u* other); 82 83//! Special optimization for use byprocessstate (and nobody else). Force_set void (t* other); +//Reset, the Void Clear (); Accessors//t& operator* () const {return *m_ptr;}----inline t* operator-> () const {return m_ptr; } 94 inline t* get () const {return m_ptr;}//Operators/98 COMPARE (= =) COMPARE (! =) 1 XX COMPARE (>) 101 COMPARE(<) 102 COMPARE (<=) 103 COMPARE (>=) 104105private:106 template<typename y>friend class sp;107 Temp Late<typename Y>friend class wp;108 void Set_pointer (t* ptr); 109 t* m_ptr;110};
66-71 rows, 5 SP constructors are defined.
73 rows, defines the SP's destructor.
77-81 rows, which defines the overloaded functions of the 4 "=" operators.
92-103 rows, overloading the other 8 operators. Each compare macro pair should have 6 overloaded functions for the operator.
109 lines, defines the T-type pointer variable m_ptr. This pointer variable m_prt is the core of the SP class.
We can understand the SP class this way:
1. An object instance of the SP class is used to replace the pointer we used originally.
2, SP class is the encapsulation of pointers. SP.M_PRT is the pointer we used originally.
3. By using an SP class object instead of a pointer, you can avoid common errors when using pointers.
Why do you use an SP class object instead of a pointer to avoid common errors when using pointers?
First of all, the first common mistake of using pointers is that they are not initialized when the pointer is defined.
When you use an SP class object in place of a pointer, the SP class constructor is called when you create the SP class object, and in the constructor, the sp.m_ptr is initialized, for example:
+ -Inline sp (): m_ptr (0) {}
The default constructor initializes sp.m_ptr to 0.
Another example:
120template<typename T>121SP<T>::SP (t* Other) 122:m_ptr (other) 123 {124 if (other) other-> Incstrong (this);
The constructor initializes the sp.m_ptr to other, passed in through the parameters.
In addition to constructors, initializing an SP object may also pass an assignment operator, for example:
sp<object> = new Object
In this case, the SP's "=" overloaded operator is used:
162template<typename t>163sp<t>& sp<t>::operator = (t* other) 164{165 if (other) other-> Incstrong (this), 166 if (m_ptr) M_ptr->decstrong (this); 167 m_ptr = other;168 return *this;169}
As you can see, in the "=" overloaded operator, 167 rows, the other assignment of the parameter passed in to Sp.m_ptr.
This avoids the first common mistake of using pointers (forgetting to initialize when defining pointers) by completing the initialization of sp.m_ptr in constructors and overloaded assignment operators.
The second common error with pointers (forget delete after new one) and a third common error (wild pointer) can be resolved by adding a reference counter to the object pointed to by the pointer. We can imagine that if the object pointed to by the pointer has a reference counter, that is, when there is a pointer to the object, the object reference counter is 1, there are two pointers to the object, the object reference counter is 2, and so on. Conversely, when a pointer no longer points to the object, the value of the object reference counter is reduced by 1, and when the object reference counter has a value of 0 o'clock, the object needs to be deleted.
How do I set a reference counter to an object? The practice of the Android smart pointer is to have the class that corresponds to the object inherit the Lightrefbase template class, which is defined in the Frameworks/rs/cpp/util/refbase.h file:
163template <class t>164class lightrefbase165{166public:167 Inline lightrefbase (): MCount (0) {}168 inline Voidincstrong (_ _ATTRIBUTE__ ((unused)) const void* ID) Const {169 __sync_fetch_and_add (&mcount, 1);}171 inline Voiddec Strong (__attribute__ ((unused)) const void* ID) Const {172 if (__sync_fetch_and_sub (&mcount, 1) = = 1) {173 Deletestatic_cast<const t*> (this); 174}175}176//! Debugging Only:getcurrent Strong ref count.177 inline Int32_tgetstrongcount () const {178 return mcount;179} 180181 typedeflightrefbase<t> basetype;182183protected:184 Inline ~lightrefbase () {}185186private:187 Frie nd classreferencemover;188 inline static void Movereferences (Void*,void const*, size_t,189 Constreferencecon verterbase&) {}190191private:192 mutable volatile int32_tmcount;193};
192 lines, defines an integer mcount, which is called the reference counter.
167 rows, the Lightrefbase constructor initializes the reference counter Mcount to 0.
168-170 rows, defines the Incstrong function, which adds 1 to the value of the reference counter Mcount.
171-175 lines, defines the Decstrong function, used to reduce the value of the reference counter Mcount 1, it should be noted that if the value of Mcount before minus 1 is 1, indicating that the last reference to this object is also dismissed, the object will be delete, This avoids what we call the new object and forgets the delete.
Knowing the definition of lightrefbase, we look back at the SP class to understand how smart pointers work.
The SP's constructor is as follows:
120template<typename T>121SP<T>::SP (t* Other) 122:m_ptr (other) 123 {124 if (other) other-> Incstrong (this);
The overloaded assignment operators for the SP are as follows:
162template<typename t>163sp<t>& sp<t>::operator = (t* other) 164{165 if (other) other-> Incstrong (this), 166 if (m_ptr) M_ptr->decstrong (this); 167 m_ptr = other;168 return *this;169}
Class T inherits Lightrefbase, and you can see that the SP object is pointed to the T object by a constructor or assignment operation, in addition to assigning the other to Sp.m_ptr, because both of these cases are added to an object reference count, so the other-> is also called Incstrong (This). It is particularly important to note that in assignment operations, if m_ptr points to other values before, you need to call M_ptr->decstrong (this), that is, the corresponding object reference count minus 1, and then assign the other to Sp.mptr.
The SP's destructor is as follows:
147template<typename t>148sp<t>::~sp () 149{150 if (m_ptr) M_ptr->decstrong (this); 151}
It is visible that when the smart pointer SP is refactored, M_ptr->decstrong (this) is called to let the corresponding object's reference counter minus 1.