从零开始写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;
}

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

相关推荐
StackNoOverflow1 小时前
MySQL Explain 返回列详解:从入门到实战,附 SQL 与避坑大全
android
CYRUS_STUDIO9 小时前
Frida 检测与对抗实战:进程、maps、线程、符号全特征清除
android·逆向
csj5010 小时前
安卓基础之《(28)—Service组件》
android
lhbian12 小时前
PHP、C++和C语言对比:哪个更适合你?
android·数据库·spring boot·mysql·kafka
catoop13 小时前
Android 最佳实践、分层架构与全流程解析(2025)
android
ZHANG13HAO14 小时前
Android 13 特权应用(Android Studio 开发)调用 AOSP 隐藏 API 完整教程
android·ide·android studio
田梓燊14 小时前
leetcode 142
android·java·leetcode
angerdream15 小时前
Android手把手编写儿童手机远程监控App之JAVA基础
android
菠萝地亚狂想曲15 小时前
Zephyr_01, environment
android·java·javascript
sTone8737515 小时前
跨端框架通信机制全解析:从 URL Schema 到 JSI 到 Platform Channel
android·前端