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

 

写在前面

用自己的话解释清楚~

 

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

什么是智能指针?

智能指针是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手册中找到了有关的解释:

unusedThis 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. 是一个单向的关系,即定义了BA的友元类,并不代表AB的友元;
  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

 

 

转载于:https://www.cnblogs.com/fly-fish/p/3854138.html

<think>好的,我现在需要帮助用户了解在Qt中使用智能指针获取对象的方法和示例。首先,我需要回忆下Qt提供的几种智能指针类型,比如QPointer、QSharedPointer、QWeakPointer和QScopedPointer,以及它们各自的用途和区别。 用户之前提到了QPointer的用法,比如构造、判空和获取裸指针,但可能还不太清楚如何具体获取对象。我需要分步骤解释每种智能指针如何获取所管理的对象,并给出示例代码。 首先,QPointer主要用于跟踪QObject及其派生类的对象,当对象被销毁时,QPointer会自动置空。获取对象的话,可以使用data()方法或者直接解引用操作符。但需要注意,QPointer并不管理对象的生命周期,所以需要确保对象存在。 接下来是QSharedPointer,这是个引用计数的智能指针,当所有引用都释放时,对象会被自动删除。获取对象的方法同样使用data()或者解引用。此外,QSharedPointer可以和QWeakPointer配合使用,QWeakPointer用于观察对象而不增加引用计数,避免循环引用。要获取对象,需要先将QWeakPointer提升为QSharedPointer,如果对象还存在的话。 然后是QScopedPointer,它独占对象所有权,离开作用域时自动释放。获取对象也是用data()或解引用,但因为所有权独占,不能复制,只能移动。 在给出示例时,需要确保代码正确,比如使用正确的语法和头文件。同时,要提醒用户注意每种指针的使用场景和注意事项,比如QPointer不管理生命周期,QWeakPointer需要检查提升是否成功等。 用户可能需要知道不同智能指针之间的区别,以及何时使用哪种指针。例如,QPointer适合观察可能被外部删除的对象,而QSharedPointer适合共享所有权的场景。还要注意Qt的智能指针与C++标准库智能指针的异同,比如QScopedPointer类似于std::unique_ptr。 最后,生成相关问题,帮助用户进步学习,比如性能影响、与标准库指针的对比、处理循环引用等。这些问题应该覆盖用户可能关心的扩展知识点,确保回答的全面性。</think>### QT智能指针获取对象的方法及示例 在QT中使用智能指针获取对象主要涉及四种智能指针类型:$QPointer$、$QSharedPointer$、$QWeakPointer$ 和 $QScopedPointer$。以下是具体用法及示例: --- #### 1. **QPointer(观察型指针)** 用于跟踪$QObject$派生类对象,当对象被删除时自动置空,但**不管理生命周期**。 ```cpp #include <QPointer> #include <QObject> QPointer<QObject> objPtr = new QObject(); // 创建QPointer if (!objPtr.isNull()) { QObject* rawPtr = objPtr.data(); // 获取裸指针 qDebug() << "对象地址:" << rawPtr; } ``` --- #### 2. **QSharedPointer(共享所有权指针)** 基于引用计数管理对象生命周期,支持多线程安全。 ```cpp #include <QSharedPointer> QSharedPointer<QObject> sharedPtr = QSharedPointer<QObject>::create(); QObject* rawPtr = sharedPtr.data(); // 直接获取对象 // 或通过操作符重载 QObject& objRef = *sharedPtr; // 解引用获取对象引用 ``` --- #### 3. **QWeakPointer(弱引用指针)** 需配合$QSharedPointer$使用,避免循环引用,需升级为$QSharedPointer$才能访问对象。 ```cpp QWeakPointer<QObject> weakPtr = sharedPtr.toWeakRef(); if (!weakPtr.isNull()) { QSharedPointer<QObject> lockedPtr = weakPtr.lock(); // 尝试升级为强引用 if (lockedPtr) { qDebug() << "对象有效:" << lockedPtr.data(); } } ``` --- #### 4. **QScopedPointer(作用域独占指针)** 对象在作用域结束时自动释放,不可复制但可转移所有权。 ```cpp #include <QScopedPointer> QScopedPointer<QObject> scopedPtr(new QObject()); QObject* rawPtr = scopedPtr.data(); // 获取对象 // 或直接操作 scopedPtr->setObjectName("MyObject"); ``` --- ### 关键区别与注意事项 | 指针类型 | 所有权管理 | 线程安全 | 适用场景 | |-------------------|--------------|----------|---------------------------| | $QPointer$ | 无 | 否 | 观察可能被外部删除的对象 | | $QSharedPointer$ | 共享所有权 | 是 | 多线程共享对象 | | $QWeakPointer$ | 无 | 是 | 打破循环引用 | | $QScopedPointer$ | 独占所有权 | 否 | 局部作用域独占资源 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值