Android中定義了兩種智能指針類型,一種是強指針sp(strong pointer),源碼中的位置在system/core/include/utils/StrongPointer.h。另外一種是弱指針(weak pointer)。其實稱之為強引用和弱引用更合適一些。強指針與一般意義的智能指針概念相同,通過引用計數來記錄有多少使用者在使用一個對象,如果所有使用者都放棄了對該對象的引用,則該對象將被自動銷毀。
弱指針也指向一個對象,但是弱指針僅僅記錄該對象的地址,不能通過弱指針來訪問該對象,也就是說不能通過弱指針來調用對象的成員函數或訪問對象的成員變量。要想訪問弱指針所指向的對象,需首先通過wp類所提供的promote()方法將弱指針升級為強指針。弱指針所指向的對象是有可能在其它地方被銷毀的,如果對象已經被銷毀,wp的promote()方法將返回空指針,這樣就能避免出現地址訪問錯的情況。
強弱智能是用來解決什么問題的呢?
1.問題是如何產生的,當我們用new 的時候,如果忘了delet。
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>using namespace std;class Person{
public:string name;Person(string n){name =n;cout<<"build person:"<<name<<endl;}void printInfo(){cout<<"i am "<<name<<endl;}~Person(){cout<<"release person:"<<name<<endl;}
};
void test_func(void)
{Person *p = new Person("zhangsan");p->printInfo();
// Person p = Person("zhangsan");
// p.printInfo();
}int main(int argc, char **argv)
{int i;for (i = 0; i < 2; i++)test_func();return 0;
}
那么問題產生了。
有內存泄露。
2.開始改進,使用局部變量
?Person *p = new Person("zhangsan");
????p->printInfo();
// ???Person p = Person("zhangsan");
// ???p.printInfo();
? ?析構函數執行,內存泄露沒有了。
結合以上兩點,繼續改進。
3.? 在一個類中包含另一個類的指針,在執行這個類的析構函數時, 刪除另一個類的指針。
#include <iostream>
#include <string.h>using namespace std;class Person{
public:Person(){cout<<"build person"<<endl;}~Person(){cout<<"release person"<<endl;}void printInfo(){cout<<"print person"<<endl;}
};class sp {
private:Person *p;public:sp() : p(0) {}sp(Person *other){cout<<"sp( Person *other)"<<endl;p = other;}sp(const sp &other){cout<<"sp(const Person *other)"<<endl;p = other.p;}~sp(){cout<<"~sp()"<<endl;if (p)delete p;}Person *operator->(){return p;}
};void test_func(sp &other)
{sp s = other;s->printInfo();
}int main(int argc, char **argv)
{sp other = new Person();test_func(other);cout<<"main() end"<<endl;return 0;
}
?sp出現了。但是還有問題, 在上面的程序中 person被創建了一次,但是被release了兩次。會產生錯誤。
4. 解決思路:引入計數,當是最后一個使用者,銷毀p。
#include <iostream>
#include <string.h>using namespace std;class Person{private:int count=0;
public:Person(){cout<<"build person"<<endl;}~Person(){cout<<"release person"<<endl;}void printInfo(){cout<<"print person"<<endl;}void incStrong(){count +=1;}void decStrong(){count -=1;}int getStrongCount(){return count;}};class sp {
private:Person *p;public:sp() : p(0) {cout<<"init sp"<<endl;}sp(Person *other){cout<<"sp( Person *other)"<<endl;p = other;p->incStrong();}sp(const sp &other){cout<<"sp(const Person *other)"<<endl;p = other.p;p->incStrong();}~sp(){cout<<"~sp()"<<endl;if (p){p->decStrong();cout<<" ~"<<p->getStrongCount()<<endl;if( p->getStrongCount() ==0){delete p;p=NULL;cout<<"delete p"<<endl;}}}Person *operator->(){cout<<"->"<<endl;return p;}
};void test_func(sp &other)
{sp s = other;s->printInfo();
}int main(int argc, char **argv)
{sp other = new Person();test_func(other);cout<<"main() end"<<endl;return 0;
}
5. 將計數count 封裝成一個基類。
6.在sp類中,引入模板。
using namespace std;class RefBase{
private:int count;
public:RefBase():count(0){}void incStrong(){count++;}void decStrong(){count--;}int getStrongCount(){return count;}
};class Person:public RefBase{public:Person(){cout<<"build person"<<endl;}~Person(){cout<<"release person"<<endl;}void printInfo(){cout<<"print person"<<endl;}};
template <typename T>
class sp {
private:T *p;public:sp() : p(0) {cout<<"init sp"<<endl;}sp(T *other){cout<<"sp( Person *other)"<<endl;p = other;p->incStrong();}sp(const sp &other){cout<<"sp(const Person *other)"<<endl;p = other.p;p->incStrong();}~sp(){cout<<"~sp()"<<endl;if (p){p->decStrong();cout<<" ~"<<p->getStrongCount()<<endl;if( p->getStrongCount() ==0){delete p;p=NULL;cout<<"delete p"<<endl;}}}T *operator->(){cout<<"->"<<endl;return p;}
};void test_func(sp<Person> &other)
{sp<Person> s = other;s->printInfo();
}int main(int argc, char **argv)
{sp<Person> other = new Person();test_func(other);cout<<"main() end"<<endl;return 0;
}
? ?一個智能指針初見雛形了。