stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结

1. auto_ptr
auto_ptr主要是用来解决资源自动释放的问题,比如如下代码:
void Function()
{
Obj*p = new Obj(20);
...
if (error occor)
throw ... 或者 retrun;
delete p;
}
在函数遇到错误之后,一般会抛异常,或者返回,但是这时很可能遗漏之前申请的资源,及时是很有经验的程序员也有可能出现这种错误,
而使用auto_ptr会在自己的析够函数中进行资源释放。也就是所说的RAII
使用auto_ptr代码如下
void Function()
{
auto_ptr<Obj> ptr( new Obj(20) );
...
if (error occur)
throw exception...
}
这样无论函数是否发生异常,在何处返回,资源都会自动释放。
需要提一下的是这是一个被c++11标准废弃的一个智能指针,为什么会被废弃,先看一下下面的代码:
auto_ptr<Obj> ptr1( new Obj() );
ptr1->FuncA();
auto_ptr<Obj> ptr2 = ptr1;
ptr2->FuncA();
ptr1->FuncA();  // 这句话会异常
为什么在把ptr1复制给ptr2之后ptr1再使用就异常了呢?
这也正是他被抛弃的主要原因。
因为auto_ptr复制构造函数中把真是引用的内存指针进行的转移,也就是从ptr1转移给了ptr2,此时,ptr2引用了Obj内存地址,而ptr1引用的内存地址为空,、
此时再使用ptr1就异常了。

2. unique_ptr
unique_ptr可以看成是auto_ptr的替代品。因为他对对象的所有权比较专一,所以才叫unique 大笑
i) 无法进行复制构造和赋值操作
auto_ptr与unique_ptr的对比:
auto_ptr<Obj> ap(new Obj() );
auto_ptr<Obj> one (ap) ; // ok
auto_ptr<Obj> two = one; //ok

unique_ptr<Obj> ap(new Obj() );
unique_ptr<Obj> one (ap) ; // 会出错
unique_ptr<Obj> two = one; //会出错
也就是说unique_ptr对对象的引用比较专一,不允许随随便便的进行转移
ii)  可以进行移动构造和移动赋值操作
unique_ptr<Obj> GetObj()
{
unique<Obj> ptr( new Obj() );
return ptr;
}
unique<Obj> ptr = GetObj();
上面的代码可以顺利执行!
什么是移动构造和移动赋值呢? 这得益于C++11的标准规范。这个知识点可以参考参考网址中的第三个。
那么如果万一我就是需要把一个unique_ptr智能指针赋值给另外一个怎么办呢?
可以使用移动函数!如下:
unique<Obj> ptr1( new Obj() );
unique<Obj> ptr2( std::move(ptr1) );
这个效果和auto_ptr直接赋值是一样的,就是ptr1不再拥有Obj对象了,所以ptr1不能再用来操作内存中的Obj对象,因为这个是手动操作的,
所以程序员自己也会更加小心。

3. shared_ptr
auto_ptr和unique_ptr都只能一个智能指针引用对象,而shared_ptr则是可以多个智能指针同时拥有一个对象。
shared_ptr实现方式就是使用引用计数。这一技术在COM中是用来管理COM对象生命周期的一个方式。
引用计数的原理是,多个智能指针同时引用一个对象,每当引用一次,引用计数加一,每当智能指针销毁了,引用计数就减一,
当引用计数减少到0的时候就释放引用的对象。这种引用计数的增减发生在智能指针的构造函数,复制构造函数,赋值操作符,析构函数中。
这种方式使得多个智能指针同时对所引用的对象有拥有权,同时在引用计数减到0之后也会自动释放内存,也实现了auto_ptr和unique_ptr的资源释放的功能。

void Function()
 {
shared_ptr<Obj> ptr1( new Obj() ); // 引用计数为1
{
shared_ptr<Obj> ptr2( ptr1 ); // 引用计数为2
{
shared_ptr<Obj> ptr3 = ptr2; // 引用计数为3
int e = 0
}
//引用计数为2
}
//引用计数为1
}
//函数返回之后引用计数为0,new 出来的Obj内存已经释放了

由于shared_ptr支持复制构造,所以他可以作为标准库容器中的元素
vector<shared_ptr<Obj>> vect;
for (int i = 0; i < 10; ++i)
{
vect.push_back( shared_ptr<Obj>( new Obj() ) );
}
vector<shared_ptr<Obj>> vect2 = vect;
这些操作是auto_ptr和unique_ptr不能实现的。
注意,智能指针默认使用delete来释放资源,如果资源是FILE*怎么办?释放的时候就需要用fclose了。
如何实现呢? 
shared_ptr构造函数可以传递一个删除器。
FILE* pStm = fopen(...);
shared_ptr<FILE> fileRes(pStm, &fclose);
或者使用一个仿函数
class FileCloser { 
     public:

void operator()(FILE* file) {

std::cout << "The FileCloser has been called with a FILE*, "

"which will now be closed.\n";

if (file!=0)

fclose(file);

}

}; 
shared_ptr<FILE> fileRes(pStm, FileCloser);
关于这点看一参考这篇文章: http://www.cnblogs.com/learn-my-life/p/3817151.html

4. weak_ptr
shared_ptr是一种强引用的关系,智能指针直接引用对象。那么这个会代码一个隐含的问题,就是循环引用,从而造成内存泄漏,即便是java语言有自己的
垃圾回收器,对这种内存泄漏也没有办法,所以循环引用对java程序员来说也是一个很值得注意的问题。首先来看一个循环引用的例子。

class Parent
{
public:
    shared_ptr<Child> child;
};

class Child
{
public:
    shared_ptr<Parent> parent;
};

void Function()
{
shared_ptr<Parent> pA(new Parent);
shared_ptr<Child> pB(new Child);
pA->child = pB;
pB->parent = pA;
}
现在来分析一下Function函数的执行过程:
1. 第一条语句使得pA引用了Parent一个指针,Parent引用计数为1
2. 第二条语句使得pB引用了Child一个指针,Child引用计数为1
3. 第三条语句,调用了shared_ptr<Child>类的赋值操作符,使得Child引用计数变为2
4. 第四条语句,调用了shared_ptr<Parent>类的赋值操作符,使得Parent引用计数变为2
5. 函数返回之前调用了shared_ptr<Parent>和shared_ptr<Child>类的析够函数,使得Child引用计数变为1,Parent引用计数变为1
看!函数执行完之后new出来的Parent和Child并没有释放,所以出现了内存泄漏。
出现泄漏的原因就是pA和pB相互引用了,导致两者所引用对象的引用计数不能减少到0,造成泄漏。
如果把第三条语句或者第四条语句任意删除一个,就不会有泄漏了。
这就是强引用所带来的问题。
weak_ptr从字面意思上可以看出是一个弱指针,不是说明这个指针的能力比较弱,而是说他对他所引用的对象的所有权比较弱,
说得更直接一点儿就是他并不拥有所引用对象的所有权,而且他还不能直接使用他所引用的对象。

在stl中,weak_ptr是和shared_ptr配合使用的,在实现shared_ptr的时候也就考虑了weak_ptr的因素。
weak_ptr是shared_ptr的观察者,它不会干扰shared_ptr所共享对象的所有权,
当一个weak_ptr所观察的shared_ptr要释放它的资源时,它会把相关的weak_ptr的指针设置为空,防止weak_ptr持有悬空的指针。
注意:weak_ptr并不拥有资源的所有权,所以不能直接使用资源。
可以从一个weak_ptr构造一个shared_ptr以取得共享资源的所有权。
void Function()
{
 shared_ptr<int> sp( new Obj() );
 assert(sp.use_count() == 1);
 weak_ptr<int> wp(sp); //从shared_ptr创建weak_ptr
 assert(wp.use_count() == 1);
 if (!wp.expired())//判断weak_ptr观察的对象是否失效
 {
  shared_ptr<int> sp2 = wp.lock();//获得一个shared_ptr
  *sp2 = 100;
  assert(wp.use_count() == 2);
 }
 assert(wp.use_count() == 1);
 return 0;
}
weak_ptr并没有重载-> 和 * 操作符,所以我们不能通过他来直接使用资源,我们可以通过lock来获得一个shared_ptr对象
来对资源进行使用,如果引用的资源已经释放,lock()函数将返回一个存储空指针的shared_ptr。 expired函数用来判断资源是否失效。
使用weak_ptr并不会增加资源的引用计数。所以对资源的引用是弱引用,利用这个特性可以解决前面所说的循环依赖问题。

class Parent
{
public:
    weak_ptr<Child> child;
};

class Child
{
public:
    weak_ptr<Parent> parent;
};

void Function()
{
shared_ptr<Parent> pA(new Parent);
shared_ptr<Child> pB(new Child);
pA->child = pB;
pB->parent = pA;
}

这个时候第三和第四条语句的执行并没有增加引用计数,从而在函数执行完成只有能自动释放内存。
从上面的分析可以看出,weak_ptr是一种辅助shared_ptr的一种智能指针,一般不单独使用,而是结合
shared_ptr一起使用。

总结:
1. 尽量使用unique_ptr而不要使用auto_ptr
2. 一般来说shared_ptr能够满足我们大部分的需求
3. weak_ptr可以避免递归的依赖关系

参考网址:
1. http://www.jellythink.com/archives/684
2. http://www.jellythink.com/archives/673
3. http://www.cnblogs.com/TianFang/archive/2013/01/26/2878356.html (c++右值引用相关知识点)
4. http://www.cnblogs.com/learn-my-life/p/3817151.html
5. http://blog.csdn.net/hp_truth/article/details/40511617
6. http://www.cppblog.com/deane/archive/2010/02/25/108428.html(c++临时对象相关知识点)
7. http://blog.csdn.net/mmzsyx/article/details/8090849
8. http://www.cnblogs.com/learn-my-life/p/3817279.html

转载于:https://www.cnblogs.com/lsgxeva/p/7668868.html

stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结相关推荐

  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++ 四种智能指针详解

    智能指针出现的原因:主要解决的是堆内存分配释放,忘记释放内存引发的内存泄漏问题,智能指针最主要的事情就是让程序员无需去注意内存释放,内存释放的问题放在智能指针内部进行处理. 智能指针有四种,包括aut ...

  3. C++的4种智能指针剖析使用

    1. 智能指针背后的设计思想 我们先来看一个简单的例子: void remodel(std::string & str) {std::string * ps = new std::string ...

  4. 学习笔记 | c++中的smart pointer四个智能指针 shared_ptr、unique_ptr、weak_ptr、auto_ptr

    c++中的smart pointer四个智能指针 C++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr其中后三个是c++11支持,并且第一个 ...

  5. 32. 对c++中的smart pointer四个智能指针shared_ptr,unique_ptr,weak_ptr,auto_ptr的理解

    C++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是c++11支持,并且第一个已经被11弃用. 智能指针的作用是管理一个指针, ...

  6. java 中lock,java中lock获取锁的四种方法

    在java接口中会存放着许多方法,方便线程使用时的直接调用.对于lock接口大家都不陌生,我们已经初步对概念进行了理解.那么在获取锁的方法上想必还不是很清楚.下面我们就lock获取锁的四种方法分别进行 ...

  7. C#中方法的参数的四种类型(转)

    转自:http://www.cnblogs.com/netlyf/p/3822956.html C#中方法的参数有四种类型: 1. 值参数类型  (不加任何修饰符,是默认的类型) 2. 引用型参数   ...

  8. 【转】Java中字符串中子串的查找共有四种方法(indexof())

    原文网址:http://wfly2004.blog.163.com/blog/static/1176427201032692927349/ Java中字符串中子串的查找共有四种方法,如下: 1.int ...

  9. html表格极细边框,html中表格细边框的四种实现及其比较

    html中表格细边框的四种实现及其比较 (4页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 html 中表格细边框的四种实现及其比较第一 ...

  10. 在Action类中获得HttpServletResponse对象的四种方法

    Struts2:在Action类中获得HttpServletResponse对象的四种方法 在struts1.x Action类的execute方法中,有四个参数,其中两个就是response和req ...

最新文章

  1. 从命令行列出所有环境变量?
  2. 黑盒测试和白盒的区别,有哪些常见的白盒黑盒测试方法
  3. DNS Tunneling及相关实现——总之,你发起攻击都需要一个DNS server,下载一些工具作为client发起数据,server收集数据并响应...
  4. mvc tips:在模板页中使用javascript
  5. (char*)x C语言中的和*的详解
  6. 基于R的信用评分卡模型解析
  7. xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance(xsi:schemaLocation详解)
  8. 同为Chromium浏览器,Edge却被“特别关照”
  9. Exchange 2010 迁移至Exchange 2013系列之六:创建信任关系并安装ADMT Server
  10. 实时音频编解码之二编码学数学知识
  11. 一文教会你使用 Neo4j 快速构建明星关系图谱
  12. 探访厦航飞机女“医生” 有机务“熊猫”美誉
  13. 2019各大互联网公司年会盘点
  14. 你管这叫操作系统源码(五)
  15. 基于jsp+mysql+ssm的爱康医院专家预约管理系统-计算机毕业设计
  16. 测试地图最短路径搜索(二):换个稍微复杂点的路径模板
  17. fortran教程5:数组
  18. Smooth Paths Using Catmull-Rom Splines
  19. win7系统定时删除数据的批处理命令_win7系统使用批处理删除文件详细教程
  20. fatal error LNK1104: 无法打开文件“..\..\Cons\Debug64\Logic.ilk”

热门文章

  1. android圆图,Android实现圆形图片或者圆角图片
  2. pcl dll load failed: 找不到指定的模块。_解决cuda10.1+tensorflow-gpu出现“cudart64_100.dll”问题...
  3. 区块链 Fisco bcos 智能合约(12)-Solidity的高级特性
  4. 2021湖南高考成绩分段查询,2021年湖南高考成绩排名查询系统,湖南高考位次排名查询...
  5. 计算机论文-中国免费,计算机硕士毕业论文免费
  6. java中的url进行编码和解码
  7. 开发板Linux内核,芯灵思SinlinxA33开发板Linux内核workqueue(附实测代码)
  8. IDEA 打包、Spring Boot Maven plugin 打包可执行 Jar 程序
  9. JQuery-Ztree 树插件下载 与 快速入门
  10. 小D课堂 - 新版本微服务springcloud+Docker教程_4-04 高级篇幅之服务间调用之负载均衡策略调整实战...