http://blog.csdn.net/wendy_keeping/article/details/75268687

智能指针的提出:智能指针是存储指向动态分配对象指针的类,用于生存期控制。能够确保正确销毁动态分配的内存,防止内存泄露。

1.智能指针的分类: 
不带引用计数的智能指针 
auto_ptr unique_ptr scoped_ptr

带引用计数的智能指针 
shared_ptr:强智能指针 
weak_ptr:若智能指针

2.不带引用计数的智能指针是如何确保正确释放堆上内存的? 
auto_ptr:

auto_ptr<A> ptr1(new A(10));
auto_ptr<A> ptr2 = ptr1;
  • 1
  • 2

当这两行代码执行完后,ptr1已经不再指向A这个对象,并且ptr1=NULL,ptr1对A对象的所有权已经转移给了ptr2,也就不能通过ptr1调用该类的方法。

vector<auto_ptr<int>> vec;

不能将auto_ptr类型的指针作为STL容器的元素。因为容器避免不了直接拷贝构造和互相赋值。auto_ptr的这种特性会给STL容器的使用造成很大的麻烦。

unique_ptr:

unique_ptr<A> ptr1(new A(10));
unique_ptr<A> ptr2 = ptr1;//error
unique_ptr<A> ptr3 = func();//ok

unique_ptr不支持拷贝构造函数和赋值运算符重载函数,不能隐式的将原指针置为NULL,但是可以通过返回值赋值。unique_ptr支持移动构造函数和移动赋值运算符重载函数,是通过move(C++11标准)函数实现的,用户明确知道对象的所有权已经发生转移,不能再使用原来的指针调用类的方法。这也是auto_ptr和unique_ptr最根本的区别。

scoped_ptr:

scoped_ptr不支持所有权的转移,只能通过该指针对对象进行操作,出作用域会自动析构。

3.带引用计数的智能指针

shared_ptr<A> pa(new A());
shared_ptr<A> pb = pa;

当使用指针指向堆上的对象时,该对象的引用计数加1。拷贝构造或赋值时,不产生该对象的副本,只是更改对象的引用计数。如果别的智能指针也指向这个对象时,也是增加其引用计数。如果delete 指针时,先对引用计数减1,直到对象的引用计数减为0,才调用该对象的析构函数。

4.智能指针的交叉引用导致内存泄露

class A
{
public:shared_ptr<B> _pb;
};
class B
{
public:shared_ptr<A> _pa;
};int main()
{shared_ptr<A> pa(new A());shared_ptr<B> pb(new B());pa->_pb = pb;pb->_pa = pa;return 0;
}

pa指针指向堆上对象后,A的引用计数是1,B的引用计数是1。 
pa->_pb = pb;此时,B的引用计数是2。 
pb->_pa = pa;此时,A的引用计数是2。

出作用域后: 
pb指针释放,B对象的引用计数减1,此时,B的引用计数是1,并不调用B的析构函数。 
pa指针释放,A对象的引用计数减1,此时,A的引用计数是1,并不调用A的析构函数。

程序运行结束,A和B对象并未析构,造成内存泄露

为了避免内存泄露,必须打断这种循环等待的现象。智能指针提供了weak_ptr(弱智能指针)可以避免产生循环等待的现象。

weak_ptr,当用weak_ptr指向对象时,对象的引用计数并不加1,因为弱智能指针没有对对象的使用权,它只有监控权。

#include <iostream>
#include <memory>
using namespace std;class A
{
public:weak_ptr<B> _pb;
};
class B
{
public:shared_ptr<A> _pa;
};int main()
{shared_ptr<A> pa(new A());shared_ptr<B> pb(new B());pa->_pb = pb;pb->_pa = pa;return 0;
}

pa指针指向堆上对象后,A的引用计数是1,B的引用计数是1。 
pa->_pb = pb;此时,B的引用计数是1。因为A的成员对象是weak_ptr。 
pb->_pa = pa;此时,A的引用计数是2。

出作用域后: 
pb指针释放,B对象的引用计数减1,此时,B的引用计数是0,调用B的析构函数,先析构自己(B被析构),再析构成员对象(A的引用计数减1,此时A的引用计数是1) 
pa指针释放,A对象的引用计数减1,此时,A的引用计数是0,调用A的析构函数(A被析构)

为了避免智能指针循环引用造成的内存泄露情况,要遵守:创建对象的时候,一定要用强智能指针,其他地方只能用持有资源的弱智能指针

智能指针本身是线程安全的。使用atomic_increment和atimic_decreament进行对多线程间的互斥,保证引用计数count++/count–是原子操作。

5.多线程访问共享的C++对象产生的线程安全的问题

#include <iostream>
#include <memory>
using namespace std;class C
{
public:C(){}~C(){}void func(){cout<<"call func()"<<endl;}
};void* threadProc(void *lparg)
{shared_ptr<C> pc = (shared_ptr<C>)lparg;pc->func();//如果对象已经析构,则程序崩溃!return NULL;
}int main(int argc, char* argv[])
{shared_ptr<C> c(new C());pthread_t tid;pthread_create(&tid, NULL, threadProc, &c);return 0;
}

多线程中可能访问共享的对象,如果对象已经析构,线程中访问它,程序会崩溃掉。解决多线程访问共享的C++对象产生的线程安全的问题,可以使用weak_ptr。将弱智能指针转给线程,再访问对象时,先将弱智能和提升为强智能指针,如果提升成功,则说明对象还存在,可以访问该对象的成员变量或方法。如果提升失败,则说明对象已经析构。


#include <iostream>
#include <memory>
using namespace std;class C
{
public:C(){}~C(){}void func(){cout<<"call func()"<<endl;}
};void* threadProc(void *lparg)
{weak_ptr<C> pw = *(weak_ptr<C>*)lparg;shared_ptr<C> pc = pw.lock();
//类型提升if(pc != NULL)
//类型提升成功,对象未析构{pc->func();}return NULL;
}int main(int argc, char* argv[])
{shared_ptr<C> c(new C());pthread_t tid;weak_ptr<C> pw(c);pthread_create(&tid, NULL, threadProc, &pw);return 0;
}

创建对象的时候一定要用强智能指针,其他地方只能用持有资源的弱智能指针!!!

C++总结8——shared_ptr和weak_ptr智能指针相关推荐

  1. 【C++】shared_ptr共享型智能指针详解

    指针是C/C++区别于其他语言的最强大的语法特性,借助指针,C/C++可以直接操纵内存内容.但是,指针的引入也带来了一些使用上的困难,这要求程序员自己必须手动地对分配申请的内存区进行管理. share ...

  2. C++新特性探究(18.3):C++11 weak_ptr智能指针

    C++11 weak_ptr智能指针 1.weak_ptr指针的创建 2.weak_ptr模板类提供的成员方法 例2: 程序执行结果为: 2 1 10

  3. C++11中的智能指针unique_ptr、shared_ptr和weak_ptr详解

    目录 1.引言 2.什么是智能指针? 3.在Visual Studio中查看智能指针的源码实现 4.独占式指针unique_ptr 4.1.查看unique_ptr的源码实现片段 4.2.为什么uni ...

  4. 深入掌握C++智能指针

    知识的学习在于点滴记录,坚持不懈:知识的学习要有深度和广度,不能只流于表面,坐井观天:知识要善于总结,不仅能够理解,更知道如何表达! 目录 智能指针介绍 自己实现智能指针 不带引用计数的智能指针 带引 ...

  5. C++11智能指针shared_ptr、weak_ptr、unique_ptr用法

    该博文为原创文章,未经博主同意不得转载,如同意转载请注明博文出处 本文章博客地址:https://cplusplus.blog.csdn.net/article/details/105065859 智 ...

  6. 智能指针shared_ptr、unique_ptr、weak_ptr

    智能指针 智能指针解决的问题 智能指针分类 shared_ptr 内存模型图 shared_ptr示例 shared_ptr含义 shared_ptr基本用法及常用函数 常用函数 智能指针的构造,初始 ...

  7. 智能指针 shared_ptr 解析

    近期正在进行<Effective C++>的第二遍阅读,书里面多个条款涉及到了shared_ptr智能指针,介绍的太分散,学习起来麻烦.写篇blog整理一下. LinJM   @HQU s ...

  8. C++新特性探究(18.1):C++11 shared_ptr智能指针

      在实际的 C++ 开发中,我们经常会遇到诸如程序运行中突然崩溃.程序运行所用内存越来越多最终不得不重启等问题,这些问题往往都是内存资源管理不当造成的.比如:   有些内存资源已经被释放,但指向它的 ...

  9. 智能指针的用法shared_ptr

    目录 智能指针 shared_ptr共享的智能指针 shared_ptr的基本用法 1.初始化 reset成员函数 make_shared swap()函数 2. 获取原始指针(get()) 3. 指 ...

最新文章

  1. 【Brain】复旦类脑研究院:破解大脑奥秘,为实现人工智能自我思考奠定基础...
  2. sublime text 3170 破解工具
  3. ZOJ 2317 Nice Patterns Strike Back(矩阵快速幂)
  4. Controller 如果能保持单例,尽量使用单例
  5. HDU - 1079 Calendar Game(博弈打表sg函数)
  6. 2020年10月21日 星期三 工作日志
  7. 线程同步,线程不同步_同步多线程集成测试
  8. Oracle特殊恢复原理与实战(DSI系列)
  9. 用微型“缝纫机”把芯片无痛“打”进大脑,Elon Musk的脑机帝国拉开序幕!|湾区人工智能...
  10. android二级菜单实现,Android编程实现二级下拉菜单及快速搜索的方法
  11. 廖雪峰git学习(3)分支管理【待续】
  12. kubernetes核心组件的运行机制
  13. cef 前进后台 实现_使用CefSharp前端后台交换
  14. python模拟人工滑动_pyppeteer 模拟人工滑动验证(一)
  15. 阿里云在安全方面有哪些防护措施
  16. shopex mysql 数据库服务器_shopex数据库优化实例
  17. Microsoft visual studio关闭安全检查的几种方法(2015/2017)
  18. 手淘抓包、 x-sign的签名算法和api接口
  19. 当mathpix 免费次数用完了怎么办?
  20. Matlab 一张图绘制在一个figure里,多张图绘制在一个figure里,和多张图分别绘制在一个figure里(多重子图)讲解及代码

热门文章

  1. 图片和文件上传js剖析
  2. Dotnet Core
  3. VB调用VC DLL函数
  4. 批量删除html网页,批量删除.html · panghuamama/Clearly Local - Gitee.com
  5. 做折线图坐标轴数字_Excel折线图表的另类表达制作?牛闪君使用了双线表达法来完成...
  6. apriori算法c++_关联分析——基于Apriori算法实现
  7. android 动态生成fragment,Android动态加载fragment(fragment复用)
  8. C++智能指针使用指南 part1:基本使用
  9. Java BigInteger类| modInverse()方法与示例
  10. setmonth_日期setMonth()方法以及JavaScript中的示例