C++11学习之share_ptr和weak_ptr
因为最近公司项目需要使用C++11,本文是在我学习share_ptr和weak_ptr过程中整理网上的资料进行写的.如有错误之处,还望小伙伴们踊跃留言.
参考资料:
http://blog.csdn.net/jiangfuqiang/article/details/8292906
http://blog.csdn.net/solstice/article/details/6395098
一、shared_ptr学习
1.shared_ptr和weak_ptr 基础概念
- shared_ptr与weak_ptr智能指针均是C++ RAII的一种应用,可用于动态资源管理
- shared_ptr基于“引用计数”模型实现,多个shared_ptr可指向同一个动态对象,并维护了一个共享的引用计数器,记录了引用同一对象的shared_ptr实例的数量。当最后一个指向动态对象的shared_ptr销毁时,会自动销毁其所指对象(通过delete操作符)。
- shared_ptr的默认能力是管理动态内存,但支持自定义的Deleter以实现个性化的资源释放动作。
- weak_ptr用于解决“引用计数”模型循环依赖问题,weak_ptr指向一个对象,并不增减该对象的引用计数器
2.shared_ptr的基本操作
#include <memory>
#include <iostream>struct Foo {Foo() { std::cout << "Foo...\n"; }~Foo() { std::cout << "~Foo...\n"; }
};struct D { //删除p所指向的Foo对象void operator()(Foo* p) const {std::cout << "Call delete for Foo object...\n";delete p;}
};int main()
{ // constructor with no managed objectstd::shared_ptr<Foo> sh1;// constructor with objectstd::shared_ptr<Foo> sh2(new Foo);std::shared_ptr<Foo> sh3(sh2);std::cout << sh2.use_count() << '\n';std::cout << sh3.use_count() << '\n';//constructor with object and deleterstd::shared_ptr<Foo> sh4(new Foo, D());
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
构造方法:
1.通过make_shared函数构造
auto s_s = make_shared(“hello”);
2.通过原生指针构造
int* pNode = new int(5);
shared_ptr s_int(pNode);
//获取原生指针
int* pOrg = s_int.get();
3.通过赋值函数构造shared_ptr
4.重载的operator->, operator *,以及其他辅助操作如unique()、use_count(), get()等成员方法。
3 实验智能指针引用计数,增加和减少的规律
实验的主要内容有:
1.shared_ptr变量在生命周期中销毁后,引用计数是否减1?
2.shared_ptr作为函数参数,分为传值和传引用,引用计数如何变化?
2.函数返回值为shared_ptr类型时,引用计数是否会变化?
带着这几个问题,我们来看下代码.
#include <iostream>
#include <memory>
using namespace std;void Func1(shared_ptr<int> a)
{cout<<"Enter Func1"<<endl;cout<<"Ref count: "<<a.use_count()<<endl;cout<<"Leave Func1"<<endl;
}shared_ptr<int> Func2(shared_ptr<int>& a)
{cout<<"Enter Func2"<<endl;cout<<"Ref count: "<<a.use_count()<<endl;cout<<"Leave Func2"<<endl;return a;
}int main()
{//构造一个指向int类型对象的指针aObj1,引用计数+1shared_ptr<int> aObj1(new int(10));cout<<"Ref count: "<<aObj1.use_count()<<endl;{//同aObj1,不过由于生存周期在括号内,所以aObj2会被销毁shared_ptr<int> aObj2 = aObj1;cout<<"Ref count: "<<aObj2.use_count()<<endl;//引用计数-1}//在调用函数时,参数为shared_ptr类型,参数为传值类型,智能指针引用计数+1Func1(aObj1);//在调用函数时,参数为shared_ptr类型,参数为传引用类型,智能指针引用计数不变Func2(aObj1);shared_ptr<int> aObj3 = Func2(aObj1);//引用计数+1cout<<"Ref count:"<<aObj3.use_count()<<endl;return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
运行结果如下:
有效的掌握好智能指针的引用计数的变化规律,才能把程序写的更好.
4. shared_ptr的应用场景以及使用注意事项
4.1 对象之间“共享数据”,对象创建与销毁“分离”
4.2 放入容器中的动态对象,使用shared_ptr包装,比unique_ptr更合适
4.3 管理“动态数组”时,需要制定Deleter以使用delete[]操作符销毁内存,因为shared_ptr并没有针对数组的特化版本(unique_ptr有针对数组的特化版本)
5.shared_ptr的线程安全问题
- 同一个shared_ptr被多个线程读,是线程安全的;
- 同一个shared_ptr被多个线程写,不是 线程安全的;
- 共享引用计数的不同的shared_ptr被多个线程写,是线程安全的。
对于第三点,我们一般采用:
对于线程中传入的外部shared_ptr对象,在线程内部进行一次新的构造,例如: sharedptr AObjTmp = outerSharedptrObj;
二、weak_ptr学习
我们先搞清楚,weak_ptr为什么出现,或者说它是为了解决什么问题而存在的(存在即合理),哈哈
class Parent
{public:shared_ptr<Child> child;
};class Child
{public:shared_ptr<Parent> parent;
};shared_ptr<Parent> pA(new Parent);
shared_ptr<Child> pB(new Child);
pA->child = pB;
pB->parent = pA;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
在Parent类中存储了指向Child类对象的智能指针成员变量,而在Child类中也存储了指向Parent类对象的智能指针成员变量,如此就会造成环形引用,这个成因在C++中很好解释.
要解决环形引用的问题,没有特别好的办法,一般都是在可能出现环形引用的地方使用weak_ptr来代替shared_ptr。说到了weak_ptr,那下面就接着总结weak_ptr吧。
下面我们来一起学习下weak_ptr这个东东
weak_ptr指向shared_ptr指针指向的对象的内存,却并不拥有该内存。
但是,使用weak_ptr成员lock,则可返回其指向内存的一个shared_ptr对象,且在所指对象内存已经无效时,返回指针空值(nullptr)。由于weak_ptr是指向shared_ptr所指向的内存的,所以,weak_ptr并不能独立存在。
#include <iostream>
#include <memory>
using namespace std;void Check(weak_ptr<int> &wp)
{shared_ptr<int> sp = wp.lock(); // 重新获得shared_ptr对象if (sp != nullptr){cout << "The value is " << *sp << endl;}else{cout << "Pointer is invalid." << endl;}
}int main()
{shared_ptr<int> sp1(new int(10));shared_ptr<int> sp2 = sp1;weak_ptr<int> wp = sp1; // 指向sp1所指向的内存cout << *sp1 << endl;cout << *sp2 << endl;Check(wp);sp1.reset();cout << *sp2 << endl;Check(wp);sp2.reset();Check(wp);system("pause");return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
学习编程最好的方式就是一步步的跟踪去调试.
借鉴上面的代码,我们在使用weak_ptr时也要当心,时刻需要判断weak_ptr对应的shared_ptr是否为空,weak_ptr并不会增加shared_ptr的引用计数.
C++11学习之share_ptr和weak_ptr相关推荐
- main 函数解析(二)—— Linux-0.11 学习笔记(六)
main函数解析(二)--Linux-0.11 学习笔记(六) 4.6 blk_dev_init函数 void blk_dev_init(void) {int i;for (i=0 ; i<NR ...
- main函数解析(一)——Linux-0.11 学习笔记(五)
main()函数解析(一)--Linux-0.11 学习笔记(五) 经过了前面的各种铺垫,终于来到了main函数.这篇博客的任务是把init/main.c讲清楚.由于牵扯到很多的函数调用,要想一次就说 ...
- kernel_mktime() 详解 —— Linux-0.11 学习笔记(四)
题目:kernel_mktime() 详解 -- Linux-0.11 学习笔记(四) 在init/main.c文件中,有一个函数static void time_init(void) 该函数读取 C ...
- setup.s 分析—— Linux-0.11 学习笔记(二)
更新记录 版本 时间 修订内容 1.0 2018-4-14 增加了"获取显示模式"这一节,AL取值的表格 标题: setup.s 分析-- Linux-0.11 学习笔记(二) 老 ...
- Windows 11学习入门
Windows 11学习入门 目录 一.Windows 11介绍 二.Windows 11发布会 三.Windows 11网页版 四.Windows 11的19个新功能 五.参考资料 一.Window ...
- Linux内核0.11学习
Linux内核0.11学习 文章目录 Linux内核0.11学习 一.计算机开机的过程 1.启动BIOS 2.BIOS 在内存中加载中断向量表和中断服务程序 Linux内核最新已经版本已经到5.18了 ...
- C++11学习笔记-----线程库std::thread
在以前,要想在C++程序中使用线程,需要调用操作系统提供的线程库,比如linux下的<pthread.h>.但毕竟是底层的C函数库,没有什么抽象封装可言,仅仅透露着一种简单,暴力美 C++ ...
- C++ 11 创建和使用共享 weak_ptr
1.为什么需要weak_ptr? 在正式介绍weak_ptr之前,我们先来回忆一下shared_ptr的一些知识.我们知道shared_ptr是采用引用计数的智能指针,多个shared_ptr实例可以 ...
- [C++11]弱引用智能指针weak_ptr初始化和相关的操作函数
弱引用智能指针 std::weak_ptr 可以看做是 shared_ptr 的助手,它不管理 shared_ptr 内部的指针.std::weak_ptr 没有重载操作符 * 和 ->,因为它 ...
最新文章
- mounted钩子函数_vue3.0项目开发(八)新特性之响应式系统watchEffect函数
- 安装smac的注意事项
- webservice(基础)
- 关于Eclipse创建Android项目时,会多出一个appcompat_v7的问题
- 不抛弃,不放弃@《士兵突击》
- 父元素 高度固定,如何使其中的文字垂直居中?
- 与计算机病毒相关的小故事,我和计算机病毒的故事2000字论文
- javafx canvas_教程:JavaFX的Canvas API概览
- python如何下载包_怎么在python中下载包
- [除一波线段树和平衡树的草]
- Flutter混编工程之高速公路Pigeon
- 2022N2观光车和观光列车司机上岗证题目及答案
- Windows下通过Git上传项目至Github
- matlab 固定收益证券,matlab计算固定收益证券学习(二)
- 如何下载台湾的硕博论文
- java se安装_安装Java SE平台
- 粒子群算法matlab代码实例使用与参数解读(二维数据)
- 计算机科学与技术专业考数媒,数字媒体技术考研考什么
- SOUI视频教程 官方论坛
- ImageColorizer:在线黑白照片免费上色
热门文章
- 程序员在很多人心里的作用...
- Spring Boot Admin 2.5.5 发布,支持在线重启服务
- 在 k8s 中使用 Kubevirt 运行管理 Windows 10 操作系统
- 这样配置,让你的 IDEA 好用到飞起来!
- Spring 与 Spring Boot 中的事件机制
- 什么是NIO?NIO的原理是什么机制?
- Spring Boot Profile使用详解及配置源码解析
- 中国式微服务技术栈2.0
- 用html CSS实现砸金蛋,css3+js 实现砸金蛋效果
- oracle degree 造成阻塞_数据库锁/阻塞分析的一种常用方法