android中的强指针和弱指针

news/2024/7/3 12:11:10 标签: android, frameworks, delete, null, include, 编程

       在Android的源代码中,经常会看到形如:sp<xxx>wp<xxx>这样的类型定义,这其实是Android中的智能指针。智能指针是C++中的一个概念,通过基于引用计数的方法,解决对象的自动释放的问题。在C++编程中,有两个很让人头痛的问题:一是忘记释放动态申请的对象从而造成内存泄露;二是对象在一个地方释放后,又在别的地方被使用,从而引起内存访问错误。程序员往往需要花费很大精力进行精心设计,以避免这些问题的出现。在使用智能指针后,动态申请的内存将会被自动释放(有点类似Java的垃圾回收),不需要再使用delete来释放对象,也不需要考虑一个对象是否已经在其它地方被释放了,从而使程序编写工作减轻不少,而程序的稳定性大大提高

    Android的智能指针相关的源代码在下面两个文件中:

    frameworks\base\include\utils\RefBase.h
    frameworks\base\libs\utils\RefBase.cpp

    涉及的类以及类之间的关系如下图所示:

 

        Android中定义了两种智能指针类型,一种是强指针spstrong pointer),一种是弱指针(weak pointer)。其实称为强引用和弱引用更合适一些。强指针与一般意义的智能指针概念相同,通过引用计数来记录有多少使用者在使用一个对象,如果所有使用者都放弃了对该对象的引用,则该对象将被自动销毁。

        弱指针也指向一个对象,但是弱指针仅仅记录该对象的地址,不能通过弱指针来访问该对象,也就是说不能通过弱指针来调用对象的成员函数或访问对象的成员变量。要想访问弱指针所指向的对象,需首先将弱指针升级为强指针(通过wp类所提供的promote()方法)。弱指针所指向的对象是有可能在其它地方被销毁的,如果对象已经被销毁,wppromote()方法将返回空指针,这样就能避免出现地址访问错的情况。

        是不是很神奇?弱指针是怎么做到这一点的呢?其实说穿了一点也不复杂,原因就在于每一个可以被智能指针引用的对象都同时被附加了另外一个weakref_impl类型的对象,这个对象中负责记录对象的强指针引用计数和弱指针引用计数。这个对象是智能指针的实现内部使用的,智能指针的使用者看不到这个对象。弱指针操作的就是这个对象,只有当强引用计数和弱引用计数都为0时,这个对象才会被销毁

        说了这么多原理,下面该看看到底智能指针该怎么使用了。假设现在有一个类MyClass,如果要使用智能指针来引用这个类的对象,那么这个类需满足下列两个前提条件:

    1这个类是基类RefBase的子类或间接子类;
   
2这个类必须定义虚构造函数,即它的构造函数需要这样定义:

          virtual  MyClass();

        满足了上述条件的类就可以定义智能指针了,定义方法和普通指针类似。比如普通指针是这样定义:

        MyClass* p_obj;

       智能指针是这样定义:

        sp<MyClass> p_obj;

        注意不要定义成 sp<MyClass>* p_obj。初学者容易犯这种错误,这样实际上相当于定义了一个指针的指针。尽管在语法上没有问题,但是最好永远不要使用这样的定义。

    定义了一个智能指针的变量,就可以象普通指针那样使用它,包括赋值、访问对象成员、作为函数的返回值、作为函数的参数等。比如:

    p_obj = new MyClass(); // 注意不要写成 p_obj = new sp<MyClass>

    sp<MyClass> p_obj2 = p_obj;

    p_obj->func();

    p_obj = create_obj();

    some_func(p_obj);

        注意不要试图delete一个智能指针,即 delete p_obj。不要担心对象的销毁问题,智能指针的最大作用就是自动销毁不再使用的对象。不需要再使用一个对象后,直接将指针赋值为NULL即可:

        p_obj = NULL;

        上面说的都是强指针,弱指针的定义方法和强指针类似,但是不能通过弱指针来访问对象的成员。下面是弱指针的示例:

        wp<MyClass> wp_obj = new MyClass();

        p_obj = wp_obj.promote(); // 升级为强指针。不过这里要用.而不是->,真是有负其指针之名啊

        …

        wp_obj = NULL;

  

        智能指针用起来是很方便,在一般情况下最好使用智能指针来代替普通指针。但是需要知道一个智能指针其实是一个对象,而不是一个真正的指针,因此其运行效率是远远比不上普通指针的。所以在对运行效率敏感的地方,最好还是不要使用智能指针为好。


http://www.niftyadmin.cn/n/1285072.html

相关文章

经典面试题-使用Spring框架能带来哪些好处?

下面列举了一些使用Spring框架带来的主要好处&#xff1a; Dependency Injection(DI) 方法使得构造器和JavaBean properties文件中的依赖关系一目了然。与EJB容器相比较&#xff0c;IoC容器更加趋向于轻量级。这样一来IoC容器在有限的内存和CPU资源的情况下进行应用程序的开发…

AtCoder Beginner Contest 154

A.题意&#xff1a;看输入输出即可 red blue 3 4 red2 4思路&#xff1a;这个题不是很难&#xff0c;但是我一上去就想要用map,然后就很悲催&#xff0c;map里面人家按照键值给你排序&#xff0c;所以输出的时候会有错&#xff01; #include<bits/stdc.h> #define pair…

经典面试题-什么是控制反转(IOC)?什么是依赖注入(DI)?

控制反转(IOC) 控制反转是应用于软件工程领域中的&#xff0c;在运行时被装配器对象来绑定耦合对象的一种编程技巧&#xff0c;对象之间耦合关系在编译时通常是未知的。在传统的编程方式中&#xff0c;业务逻辑的流程是由应用程序中的早已被设定好关联关系的对象来决定的。在使…

利用反转函数确定回文串

题意&#xff1a;给出一个字符串&#xff0c;然后让你判断是否为回文串&#xff0c;是得话输出YES&#xff0c;否则输出NO 思路&#xff1a;我们可以直接利用string 跟 reverse&#xff08;&#xff09;函数解决这个问题 #include<bits/stdc.h>using namespace std;int…

android中的binder通信机制

Binder机制是android中实现的进程间通信的架构&#xff0c;它采用的是c/s架构&#xff0c;client通过代理完成对server的调用。ServiceManager既然这里提到了server&#xff0c;那么我们有必要先了解下在android中是怎么来管理server的。先来看一个重要的Native进 程&#xff1…

经典面试题-请解释下Spring框架中的IoC?

Spring中的 org.springframework.beans 包和 org.springframework.context包构成了Spring框架IoC容器的基础。BeanFactory 接口提供了一个先进的配置机制&#xff0c;使得任何类型的对象的配置成为可能。ApplicationContex接口对BeanFactory&#xff08;是一个子接口&#xff0…

mediarecorder中的方法以及工作流程的过程

嵌套、关联的类 class MediaRecorder.AudioEncoder 定义音频编码 class MediaRecorder.AudioSource 定义声音资源 interface MediaRecorder.OnErrorListener Interface definition for a callback to be invoked when an error occurs while recording. interface M…

经典面试题-BeanFactory和ApplicationContext有什么区别?

BeanFactory 可以理解为含有bean集合的工厂类。BeanFactory 包含了种bean的定义&#xff0c;以便在接收到客户端请求时将对应的bean实例化。BeanFactory还能在实例化对象的时生成协作类之间的关系。此举将bean自身与bean客户端的配置中解放出来。BeanFactory还包含了bean生命周…