从零开始写android 的智能指针

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;
}

一个智能指针初见雏形了。

相关推荐
stevenzqzq6 小时前
android中dp和px的关系
android
一一Null8 小时前
Token安全存储的几种方式
android·java·安全·android studio
JarvanMo9 小时前
flutter工程化之动态配置
android·flutter·ios
时光少年12 小时前
Android 副屏录制方案
android·前端
时光少年12 小时前
Android 局域网NIO案例实践
android·前端
alexhilton12 小时前
Jetpack Compose的性能优化建议
android·kotlin·android jetpack
流浪汉kylin12 小时前
Android TextView SpannableString 如何插入自定义View
android
火柴就是我14 小时前
git rebase -i,执行 squash 操作 进行提交合并
android
你说你说你来说14 小时前
安卓广播接收器(Broadcast Receiver)的介绍与使用
android·笔记
你说你说你来说14 小时前
安卓Content Provider介绍及使用
android·笔记