• 智能指针出现的原因:主要解决的是堆内存分配释放,忘记释放内存引发的内存泄漏问题,智能指针最主要的事情就是让程序员无需去注意内存释放,内存释放的问题放在智能指针内部进行处理。
  • 智能指针有四种,包括auto_ptr,shared_ptr,unique_ptr,weak_ptr,其中auto_ptr已经被C++11废弃,所以放在最后介绍。

unique_ptr


unique_ptr的几个重要特性

  • 1.两个unique_ptr不能指向一个对象,即unique_ptr不能共享它所管理的对象,这句话个人的理解的,unique_ptr无法赋值指针到另一个指针,让他们指向同一个对象。
    简单的示例代码:
class A{public:A(){cout << "demo"<< endl;}void B(){cout << "测试" << endl;}
};void unique_ptr_use()
{unique_ptr<A> A_ptr(new A());A_ptr->B();cout << A_ptr << endl;unique_ptr<A> demo = A_ptr; //此时编译错误,无法通过赋值的方式传递指针地址,即与demo共享同一块内存
}

由上面代码可以看出,编译unique_ptr<A> demo = A_ptr会报错,因为unique_ptr是只能单独享有对对象的独有权。
另外,unique_ptr无法通过赋值的形式创建内存对象,即:

这种方式也是错误的。

  • 2.提前释放unique_ptr对象可以通过reset方法进行重置
    示例代码:
void unique_ptr_use()
{unique_ptr<A> A_ptr(new A());A_ptr->B();cout << A_ptr << endl;A_ptr.reset();cout << A_ptr << endl;
}

运行结果:

可以看出:
通过reset方法 可以直接删除原始指针,并且重置为空。

  • 3.我们可以通过转移所有权的方式,来使另一个指针拥有原先unique_ptr的地址
    示例代码:
void unique_ptr_use()
{unique_ptr<A> A_ptr(new A());A_ptr->B();cout << A_ptr << endl;unique_ptr<A>BB = std::move(A_ptr);cout << A_ptr << endl;cout << BB << endl;
}

运行结果:


通过std::move()方法,将A_ptr的对象转移到BB上面,A_ptr指针为空,BB拥有A_ptr指向的地址。

  • release()方法会释放原有的原始指针,但是不会删除原先的指针,删除原先的指针需要通过reset()方法
    示例代码:
void unique_ptr_use()
{unique_ptr<A> A_ptr(new A());A_ptr->B();cout << A_ptr << endl;A * nn  = A_ptr.release();cout << nn << endl;cout << A_ptr << endl;delete nn;nn = nullptr;cout << nn << endl;
}

运行结果:

  • 知识点:使用delete删除指针,编译器只会释放原先指向的内存空间,不会释放指针本身,所以需要通过设置指针为空来删除指针本身!!!
  • 4.使用get方法 获取关联的指针对象
void unique_ptr_use()
{unique_ptr<A> A_ptr(new A());A_ptr->B();A * m = A_ptr.get();cout << "11---" << m << endl;cout << A_ptr << endl;A * nn  = A_ptr.release();cout << nn << endl;cout << A_ptr << endl;delete nn;nn = nullptr;cout << nn << endl;
}

运行结果:


shared_ptr


shared_ptr可以实现多个对象共同托管一个指针,这个是unique_ptr做不到的。当曾经的托管对象接触对其托管时,系统会自动执行delete p释放内存,这样保证了内存不会泄漏。

  • shared_ptr:可以查看赋值对象的个数,因为可以多个对象共同托管,所以个数需要获得,已经内置了一个use_count()方法返回当前可以操作该指针的对象个数。
  • 示例代码:
void shared_ptr_use()
{shared_ptr<A> mm = make_shared<A>();mm->B();cout <<"mm value:" << mm << endl;shared_ptr<A> ff(mm);cout << "ff value:" << ff << endl;cout << "个数为" << ff.use_count() << endl;mm.reset();//重置cout <<"now ff:"<< ff << endl;cout << "个数为" << ff.use_count() << endl;cout <<"now mm:"<< mm << endl;
}
  • 运行结果:

weak_ptr


  • 首先,weak_ptr不能直接定义一个对象类,需要配合shared_ptr进行使用,通过shared_ptr传指针地址给它。
  • weak_ptr主要解决的一个问题是shared_ptr相互引用无法释放内存的问题。
  • 实例代码:
class B;
class A{public:A(){cout << "A init!" << endl;}~A(){cout << "A Destroy" << endl;}void set_quote_ptr(shared_ptr<B>mm){m_b = mm;}
private:shared_ptr<B> m_b;
};class B{public:B(){cout << "A init!" << endl;}~B(){cout << "A Destroy" << endl;}void set_quote_ptr(shared_ptr<A>mm){m_a = mm;}
private:shared_ptr<A> m_a;
};void test_ptr()
{shared_ptr<A>a_ptr = make_shared<A>();shared_ptr<B>b_ptr = make_shared<B>();a_ptr->set_quote_ptr(b_ptr);b_ptr->set_quote_ptr(a_ptr);cout << "a count" << a_ptr.use_count() << endl;cout << "b count" << b_ptr.use_count() << endl;
}int main()
{test_ptr();system("pause");return 0;
}

此时他们之前存在相互引用,但是已经方法已经返回了还没稀释
运行结果:

解释原因可以参考:https://blog.csdn.net/albertsh/article/details/82286999#commentBox:解释了无法析构的原因,这里简单介绍一下。主要是相互引用时,导致引用记数无法为0;所以无法调用函数进行析构。

  • 接下来解决的方案,是使用weak_ptr来替代其中一个shared_ptr,因为这样赋值的话,不会引发计数变化,修改完的代码如下:
#include "stdafx.h"
#include <iostream>
#include <memory>
using namespace std;class B;
class A{public:A(){cout << "A init!" << endl;}~A(){cout << "A Destroy" << endl;}void set_quote_ptr(shared_ptr<B>mm){m_b = mm;}
private:weak_ptr<B> m_b;
};class B{public:B(){cout << "A init!" << endl;}~B(){cout << "A Destroy" << endl;}void set_quote_ptr(shared_ptr<A>mm){m_a = mm;}
private:weak_ptr<A> m_a;
};void test_ptr()
{shared_ptr<A>a_ptr = make_shared<A>();shared_ptr<B>b_ptr = make_shared<B>();a_ptr->set_quote_ptr(b_ptr);b_ptr->set_quote_ptr(a_ptr);cout << "a count" << a_ptr.use_count() << endl;cout << "b count" << b_ptr.use_count() << endl;
}int main()
{test_ptr();system("pause");return 0;
}

运行结果:

可以明显的看出,已经被析构了。

  • weak_ptr还有两个主要的方法lock()expired(),这边简单介绍一下
  • expired主要判断赋值给他的shared_ptr对象是否还在,在的话返回1,不在的话返回0
  • lock()返回赋值它的shared_ptr对象。
    实例代码:
// Weak_Ptr_Use.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <memory>
using namespace std;class B;
class A{public:A(){cout << "A init!" << endl;}~A(){cout << "A Destroy" << endl;bool is_fired = m_b.expired();cout << "endl:" << is_fired << endl;}void set_quote_ptr(shared_ptr<B>mm){m_b = mm;}weak_ptr<B> m_b;
};class B{public:B(){cout << "B init!" << endl;}~B(){cout << "B Destroy" << endl;}void set_quote_ptr(shared_ptr<A>mm){m_a = mm;}void show(){cout << "调用B方法测试" << endl;}
private:weak_ptr<A> m_a;
};void test_ptr()
{shared_ptr<A>a_ptr = make_shared<A>();shared_ptr<B>b_ptr = make_shared<B>();a_ptr->set_quote_ptr(b_ptr);b_ptr->set_quote_ptr(a_ptr);weak_ptr<B> b_weak_ptr = b_ptr;if (b_weak_ptr.expired()){b_weak_ptr.lock()->show();}cout << "a count" << a_ptr.use_count() << endl;cout << "b count" << b_ptr.use_count() << endl;
}int main()
{test_ptr();system("pause");return 0;
}

运行结果:


auto_ptr


  • 简单来说,auto_ptr和unique_ptr比较像,但是auto_ptr具备拷贝语义,unique_ptr只有转移所有权的方式
    代码示例:
// Weak_Ptr_Use.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <memory>
using namespace std;class A
{public:A(){cout << "A Init" << endl;}~A(){cout << "A Destory" << endl;}void show(){cout << "demo" << endl;}
};void test_auto_demo()
{unique_ptr<A> mma(new A());cout << mma << endl;auto_ptr<A> A_PTR(new A());auto_ptr<A>mm = A_PTR; //实质和std::move()语义一样。cout << mm.get() << endl;cout << A_PTR.get() << endl;A_PTR->show();
}int main()
{test_auto_demo();system("pause");return 0;
}

运行结果:

造成在这个的原因是auto_ptr<A>mm = A_PTR; //实质和std::move()语义一样。
这边A_PTR已经把所有权转给mm,此时A_PTR为空指针,空指针必然报错。。
所以unique_ptrauto_ptr更加安全,实质上个人觉得应该是编译器对unique_ptr的处理更加灵活。


智能指针的应用场景


C++ 四种智能指针详解相关推荐

  1. C++ STL 四种智能指针

    文章目录 0.前言 1.unique_ptr 2.auto_ptr 3.shared_ptr 3.1 shared_ptr 简介 3.2 通过辅助类模拟实现 shared_ptr 4.weak_ptr ...

  2. C++ 智能指针详解

    智能指针内容很多,重点是基本用法. #include <boost/shared_ptr.hpp> class CBase: public boost::enable_shared_fro ...

  3. 【C++】智能指针详解

    相关博文<C++ STL 四种智能指针> 参考资料:<C++ Primer中文版 第五版> 我们知道除了静态内存和栈内存外,每个程序还有一个内存池,这部分内存被称为自由空间或者 ...

  4. C++-智能指针详解

    引言 除了静态内存和栈内存外,每个程序还有一个内存池,这部分内存被称为自由空间或者堆.程序用堆来存储动态分配的对象即那些在程序运行时分配的对象,当动态对象不再使用时,我们的代码必须显式的销毁它们. 在 ...

  5. mvc ajax提交html标签,Mvc提交表单的四种方法全程详解

    Mvc提交表单的四种方法全程详解 2019-01-05 编程之家 https://www.jb51.cc 编程之家收集整理的这篇文章主要介绍了Mvc提交表单的四种方法全程详解,编程之家小编觉得挺不错的 ...

  6. 四种形态图解_中纪委”四种形态“指标体系详解

    中纪委"四种形态"指标体系详解 中纪委自提出"四种形态"以来,官方.民间一直对"四种 形态"各包含什么内容, 在具体实践中如何应用, 存在较 ...

  7. 文件服务器文件多备份方案,FileYee数据备份四种备份方案详解

    原标题:FileYee数据备份四种备份方案详解 其实有很多用户对FileYee数据备份软件不是特别熟悉,今天小编带大家了解一下FileYee的四种备份方案,一定会让大家对于数据备份有一个新的了解. 之 ...

  8. JVM之垃圾收集机制四种GC算法详解

    JVM之四种GC算法详解 目录: 什么是GC? GC算法之引用计数法 GC算法之复制算法(Copying) GC算法之标记清除(Mark-Sweep) GC算法之标记压缩(Mark-Compact) ...

  9. C++智能指针详解(auto_ptr、unique_ptr、shared_ptr)

    文章目录 1. 智能指针的应用场景 2. 智能指针的介绍 3. 智能指针的使用与原理 3.1 auto_ptr 3.2 unique_ptr 3.3 shared_ptr 3.4 shared_ptr ...

最新文章

  1. 基于pytorch的模型剪枝+模型量化+BN合并+TRT部署(cifar数据)(2)
  2. Office 2016 for Mac 15.24已推送至Office Insider慢速更新通道
  3. oracle 11g安装桌面,Lubuntu 12.10 桌面版安装Oracle 11g
  4. VTK:PolyData之ThresholdPoints
  5. HMM——前向算法与后向算法
  6. 安全删除U盘时,遇到提示“无法停止‘通用卷’设备时解决方法
  7. 实现与优化深度神经网络
  8. linux dns区域传送,Linux DNS服务器主从复制及区域传送
  9. Java把表导出成Excel的代码
  10. VMWare虚拟机下为Windows Server 2012配置静态IP(NAT方式)
  11. NW.js 简介与使用
  12. DeepFake技术--DeepFake克星来了,简单两步算法造假图像无处可逃
  13. MyBatis中association,collection多表查询(resultMap高级映射)笔录
  14. adb提示已停止工作问题的解决方案
  15. 星外系统更换短信接口
  16. Arx常用代码《转》
  17. GO语言实现用户注册方法(互亿无线)
  18. 自来水管道铺设问题——数学建模
  19. web页面的性能优化以及SEO
  20. 理解ARC在Objective-C中的应用

热门文章

  1. 小林求职记(四)不会吧不会吧,面试还真会问这些呀
  2. VCL组件之编辑控件
  3. 【软件体系结构】架构风格与基于网络应用软件的架构设计:Roy Tomas Fielding】
  4. 如何基于TensorFlow使用LSTM和CNN实现时序分类任务
  5. 文献阅读005【精读】
  6. ubuntu和centos 编译安装nginx及常用命令
  7. WCF技术剖析之二十八:自己动手获取元数据[附源代码下载]
  8. 第3章2节《MonkeyRunner源码剖析》脚本编写示例: MonkeyDevice API使用示例(原创)
  9. pycharm创建python虚拟环境好处_PyCharm虚拟环境创建Django2项目一些问题的解决方案...
  10. centos7安装详细图解_开封温包规格,电热执行器安装详细图解