解释清楚智能指针一【用自己的话,解释清楚】

写在前面

用自己的话解释清楚~

智能指针是什么,可分为哪几种类型,各有什么特点,解决了什么问题,怎么解决的?

什么是智能指针?

智能指针是C++中的一个概念,主要是通过引用计数的方式,解决动态内存的自动释放问题(类似于Java 、Python中的垃圾回收)。主要解决程序常见的两个问题:动态的申请的内存没有释放;动态申请的内存释放后又被引用。

指针和引用的区别:

指针其实是一个变量,只不过它存储的是另一个变量的内存地址。而引用是另外一个变量的别名,它不占用空间。所以引用定义的时候必须初始化。引用访问对象是直接访问,指针访问对象是间接访问。

他们在源码中的位置

http://androidxref.com/4.4.3_r1.1/xref/frameworks/rs/cpp/util/RefBase.h

http://androidxref.com/4.4.3_r1.1/xref/frameworks/rs/server/RefBase.h

http://androidxref.com/4.4.3_r1.1/xref/system/core/libutils/RefBase.cpp

http://androidxref.com/4.4.3_r1.1/xref/system/core/include/utils/RefBase.h

据观察他们的实现,略有差异,不过对外功能是一致的。在此以前两者为例子。

Android  源码中设计了三个智能指针:

轻量化指针(Light Pointer)、强指针(Strong Pointer)和弱指针(Weak Pointer)。

各指针的特点

强指针:

它会记录对它所指对象的引用次数,当引用次数为0时,自动释放该内存。

弱指针:

它会保存所指向对象的地址。但要引用该对象时,需要先将弱指针升级为强指针,然后再引用。如果该对象已经释放,则升级失败。

轻量级指针源码分析:

163template <class T>

164class LightRefBase

165{

166public:

167    inline LightRefBase() : mCount(0) { }

168    inline void incStrong(__attribute__((unused)) const void* id) const {

169        __sync_fetch_and_add(&mCount, 1);

170    }

171    inline void decStrong(__attribute__((unused)) const void* id) const {

172        if (__sync_fetch_and_sub(&mCount, 1) == 1) {

173            delete static_cast<const T*>(this);

174        }

175    }

176    //! DEBUGGING ONLY: Get current strong ref count.

177    inline int32_t getStrongCount() const {

178        return mCount;

179    }

180

181    typedef LightRefBase<T> basetype;

182

183protected:

184    inline ~LightRefBase() { }

185

186private:

187    friend class ReferenceMover;

188    inline static void moveReferences(void*, void const*, size_t,

189            const ReferenceConverterBase&) { }

190

191private:

192    mutable volatile int32_t mCount;

193};

备注:

__sync_fetch_and_add()

__sync_fetch_and_sub()

用于增减mCount;

无锁编程函数(参考文章:Multithreaded simple data type access and atomic variables

__attribute__((unused))

在分析系统代码时注意到有些函数会有添加__attribute__((unused)),

在gcc手册中找到了有关的解释:

unused:This attribute, attached to a function, means that the function is meant to be
        possibly unused. GCC will not produce a warning for this function.

======================================================================

used: This attribute, attached to a function, means that code must be emitted for the
       function even if it appears that the function is not referenced. This is useful,
       for example, when the function is referenced only in inline assembly.

表示该函数或变量可能不使用,这个属性可以避免编译器产生警告信息。

强弱指针源码分析

http://androidxref.com/4.4.3_r1.1/xref/system/core/include/utils/StrongPointer.h

29template<typename T> class wp;

//类似于普通类的声明,  这是一个模板类wp的声明,前面的template<typename T>  说//明它是一个模板类,用到的泛型类型  模板类中以T替代

30

31//------------------------------------------------------------------

32

33#define COMPARE(_op_)                                           \

34inline bool operator _op_ (const sp<T>& o) const {              \

35    return m_ptr _op_ o.m_ptr;                                  \

36}

\

37inline bool operator _op_ (const T* o) const {                  \

38    return m_ptr _op_ o;                                        \

39}                                                               \

40template<typename U>                                            \

41inline bool operator _op_ (const sp<U>& o) const {              \

42    return m_ptr _op_ o.m_ptr;                                  \

43}                                                               \

44template<typename U>                                            \

45inline bool operator _op_ (const U* o) const {                  \

46    return m_ptr _op_ o;                                        \

47}                                                               \

48inline bool operator _op_ (const wp<T>& o) const {              \

49    return m_ptr _op_ o.m_ptr;                                  \

50}                                                               \

51template<typename U>                                            \

52inline bool operator _op_ (const wp<U>& o) const {              \

53    return m_ptr _op_ o.m_ptr;                                  \

54}

55

56//-------------------------------------------------------------------

57

58template<typename T>

59class sp {

60public:

61    inline sp() : m_ptr(0) { }

62

63    sp(T* other);

64    sp(const sp<T>& other);

65    template<typename U> sp(U* other);

66    template<typename U> sp(const sp<U>& other);

67

68    ~sp();

69

70    // Assignment

71

72    spoperator = (T* other);

73    spoperator = (const sp<T>& other);

74

75    template<typename U> spoperator = (const sp<U>& other);

76    template<typename U> spoperator = (U* other);

77

78    //! Special optimization for use by ProcessState (and nobody else).

79    void force_set(T* other);

80

81    // Reset

82

83    void clear();

84

85    // Accessors

86

87    inline  T&      operator* () const  { return *m_ptr; }

88    inline  T*      operator-> () const { return m_ptr;  }

89    inline  T*      get() const         { return m_ptr; }

90

91    // Operators

92

93    COMPARE(==)

94    COMPARE(!=)

95    COMPARE(>)

96    COMPARE(<)

97    COMPARE(<=)

98    COMPARE(>=)

99

100private:

101    template<typename Y> friend class sp;

102    template<typename Y> friend class wp;

103    void set_pointer(T* ptr);

104    T* m_ptr;

105};

106

107#undef COMPARE

109//------------------------------------------------------------------

110// No user serviceable parts below here.

111

112template<typename T>

113sp<T>::sp(T* other)

114        : m_ptr(other) {

115    if (other)

116        other->incStrong(this);

117}

118

119template<typename T>

120sp<T>::sp(const sp<T>& other)

121        : m_ptr(other.m_ptr) {

122    if (m_ptr)

123        m_ptr->incStrong(this);

124}

125

126template<typename T> template<typename U>

127sp<T>::sp(U* other)

128        : m_ptr(other) {

129    if (other)

130        ((T*) other)->incStrong(this);

131}

132

133template<typename T> template<typename U>

134sp<T>::sp(const sp<U>& other)

135        : m_ptr(other.m_ptr) {

136    if (m_ptr)

137        m_ptr->incStrong(this);

138}

139

140template<typename T>

141sp<T>::~sp() {

142    if (m_ptr)

143        m_ptr->decStrong(this);

144}

145

146template<typename T>

147sp<T>& sp<T>::operator =(const sp<T>& other) {

148    T* otherPtr(other.m_ptr);

149    if (otherPtr)

150        otherPtr->incStrong(this);

151    if (m_ptr)

152        m_ptr->decStrong(this);

153    m_ptr = otherPtr;

154    return *this;

155}

156

157template<typename T>

158sp<T>& sp<T>::operator =(T* other) {

159    if (other)

160        other->incStrong(this);

161    if (m_ptr)

162        m_ptr->decStrong(this);

163    m_ptr = other;

164    return *this;

165}

166

167template<typename T> template<typename U>

168sp<T>& sp<T>::operator =(const sp<U>& other) {

169    T* otherPtr(other.m_ptr);

170    if (otherPtr)

171        otherPtr->incStrong(this);

172    if (m_ptr)

173        m_ptr->decStrong(this);

174    m_ptr = otherPtr;

175    return *this;

176}

177

178template<typename T> template<typename U>

179sp<T>& sp<T>::operator =(U* other) {

180    if (other)

181        ((T*) other)->incStrong(this);

182    if (m_ptr)

183        m_ptr->decStrong(this);

184    m_ptr = other;

185    return *this;

186}

187

188template<typename T>

189void sp<T>::force_set(T* other) {

190    other->forceIncStrong(this);

191    m_ptr = other;

192}

193

194template<typename T>

195void sp<T>::clear() {

196    if (m_ptr) {

197        m_ptr->decStrong(this);

198        m_ptr = 0;

199    }

200}

201

202template<typename T>

203void sp<T>::set_pointer(T* ptr) {

204    m_ptr = ptr;

205}

206

207}; // namespace android

208

209//----------------------------------------------------------------

Sp中可使用decStrong()等函数,是由于所有项使用强指针sp的类必须继承自RefBase类(decStrong()等函数  是RefBase类的成员函数)。

100private:

101    template<typename Y> friend class sp;

对这段代码的理解:

先说明一下友元类的作用

C++的设计中类的出现是为了提高程序的独立性和封装性。类中使用了关键字public 和private来定义了类中成员的访问权限,一般情况下,非类成员函数式不能访问类的内部成员函数或变量的。

但,有些情况可能需要这样,所以出C++的设计者设计了友元类这个类与类之间的关系,

它的特点是

  1. 是一个单向的关系,即定义了B是A的友元类,并不代表A是B的友元;
  2. 不具备传递性

这段代码中定义类模板类sp是模板类sp的友元类,是为了可以访问传递进来的其他类型的模板类sp的对象的私有成员变量(这里主要是m_ptr)。

比如重载的操作符==

40template<typename U>                                            \

41inline bool operator _op_ (const sp<U>& o) const {              \

42    return m_ptr _op_ o.m_ptr;

如果没有定义为友元类,就不能访问传递进来的 对象o的私有变量o.m_ptr

QQ群 计算机科学与艺术  272583193

加群链接:http://jq.qq.com/?_wv=1027&k=Q9OxMv

解释清楚智能指针一【用自己的话,解释清楚】

时间: 2024-10-18 05:59:39

解释清楚智能指针一【用自己的话,解释清楚】的相关文章

解释清楚智能指针二【用自己的话,解释清楚】

写在前面 用自己的话分析清楚~ 智能指针是如何使用的? 强指针是如何实现? 弱指针如何转化为强指针? 智能指针的使用 智能指针的使用必须满足如下条件: 这个类需要继承自RefBase 为什么需要虚析构函数? 虚析构函数是为了解决这样的一个问题:基类的指针指向派生类对象,并用基类的指针删除派生类对象.虚函数的出现是为了解决多态问题. 满足上述条件的类就可以定义智能指针了,普通的指针使用如下方式: MyClass *p_obj; 智能指针是这样定义: Sp<MyClass> p_obj; 强指针的

浅谈RAII&智能指针

关于RAII,官方给出的解释是这样的"资源获取就是初始化".听起来貌似不是很懂的哈,其实说的通俗点的话就是它是一种管理资源,避免内存泄漏的一种方法.它可以保证在各种情况下,当你对对象进行使用时先通过构造函数来进行资源的分配和初始化,最后通过析构函数来进行清理,有效的保证了资源的正确分配和释放.(特别是在异常中,因为异常往往会改变代码正确的执行顺序,这就很容易引起资源管理的混乱和内存的泄漏) 其中智能指针就是RAII的一种实现模式,所谓的智能就是它可以自动化的来管理它所指向那份空间的资源

引用内部函数绑定机制,R转义字符,C++引用,别名,模板元,宏,断言,C++多线程,C++智能指针

 1.引用内部函数绑定机制 #include<iostream> #include<functional> usingnamespacestd; usingnamespacestd::placeholders; //仿函数.创建一个函数指针,引用一个结构体内部或者一个类内部的共同拥有函数 structMyStruct { voidadd(inta) { cout <<a <<endl; } voidadd2(inta,intb) { cout <&

“智能指针”的成长

智能指针是什么,他的真面目就是一个类生成的对象,这个类中包含了基本的重载->.*等一些指针形态的用法,最主要的是这个类里面有一个指针参数:所有智能指针类中都有一个explicit构造函数,以指针作为参数.比如auto_ptr的类模板原型为: template<class T> class auto_ptr{ explicit auto_ptr(T* p = 0); }; 代码中构造函数用了explicit关键字主要是防止隐式转换,举个例子: auto_ptr<double>

Chromium和WebKit的智能指针实现原理分析

C++不像Java一样,由虚拟机负责对象分配和释放.也就是说,开发人员使用C++编写代码时,要自己负责对象分配和释放.WebKit和Chromium都是使用C++开发的,因此它们也面临上述问题.在解决对象释放问题时,要做到在对象不需要时自动释放,因为手动释放会带来忘记释放或者释放后又继续使用的隐患.智能指针是实现对象自动释放的有效技术手段.本文就分析Chromium和WebKit的智能指针的实现. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 在现实中,

【C++】智能指针详解(四):shared_ptr

在开始本文内容之前,我们再来总结一下,前文内容: 1.智能指针采用RAII机制,在构造对象时进行资源的初始化,析构对象时进行资源的清理及汕尾. 2.auto_ptr防止拷贝后析构释放同一块内存,采用"转移所有权"的方法.(实际开发中auto_ptr并不实用) 3.scoped_ptr与auto_ptr类似,但是它与auto_ptr最大的区别是:它不能转移所有权,即就是禁止拷贝/赋值!(当然,我们也探讨了C++中禁止拷贝对象的技术,在此不赘述) 回顾完前文内容后,我们今天来讨论share

【C++】智能指针详解(一):智能指针的引入

智能指针是C++中一种利用RAII机制(后面解释),通过对象来管理指针的一种方式. 在C++中,动态开辟的内存需要我们自己去维护,在出函数作用域或程序异常退出之前,我们必须手动释放掉它,否则的话就会引起内存泄漏. 例如:我们用指针变量来创建对象时,需要手动来删除它 string * pstr = new string("hello world!"); .... delete pstr; 事实上,即使我们非常谨慎,但有时候的一些情况仍然会让我们防不胜防: //情况一:在程序某个分支内,忘

enote笔记法使用范例(2)——指针(1)智能指针

要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在<C++ Primer>这样解释的,“通过定义一个类来封装资源的分配和释放,可以保证正确释放资源” 核心:C++98提供了语言机制:对象([!值语意对象])在超出作用域,,析构函数会被自动调用 [如果构造函数中抛出异常,则不会调用析构函数.只有构造函数正确地执行,构建对象成功,才会调用析构函数] &l

C++:浅谈c++资源管理以及对[STL]智能指针auto_ptr源码分析,左值与右值

C++:浅谈c++资源管理以及对[STL]智能指针auto_ptr源码分析 by 小威威 1. 知识引入 在C++编程中,动态分配的内存在使用完毕之后一般都要delete(释放),否则就会造成内存泄漏,导致不必要的后果.虽然大多数初学者都会有这样的意识,但是有些却不以为意.我曾问我的同学关于动态内存的分配与释放,他的回答是:"只要保证new和delete成对出现就行了.如果在构造函数中new(动态分配内存),那么在析构函数中delete(释放)就可以避免内存泄漏了!" 事实果真如此么?