当前位置: 首页 > news >正文

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

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

相关文章:

  • 小程序网站开发口碑营销ppt
  • wordpress发布产品seo搜索优化网站推广排名
  • 古董做推广哪个网站好百度推广客户端下载安装
  • 微信开发哪家公司好河池网站seo
  • 最优网站建设seo整站优化服务
  • 做网站推广启信聚客通网络营销策划
  • vue watch 和 watchEffect的区别和用法
  • C++:日期类,运算符重载,深浅拷贝问题
  • python:面向对象之包
  • 2025.04.10-拼多多春招笔试第四题
  • MySQL的半同步模式
  • 中间件-消息队列
  • 网络3 子网掩码 划分ip地址
  • h265为什么没有大范围应用
  • C/C++共有的类型转换与c++特有的四种强制类型转换
  • MySQL——存储过程、索引
  • 融智学三大定律:打开人机协同智慧大门的钥匙
  • 深度分页及优化建议
  • 【前端】【难点】前端富文本开发的核心难点总结与思路优化
  • 飞书集成衡石ChatBot实战:如何10分钟搭建一个业务数据问答机器人?
  • 期望理论解析
  • MCP基础学习三:MCP客户端开发与工具集成
  • linux系统编程里面的嵌套锁
  • 强化学习算法系列(二):Model-Free类方法——蒙特卡洛算法(MC)和时序差分算法(TD)
  • Linux 多线程
  • K_KMS工具(适用windows和office)