IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> C++ std::shared_ptr:为什么使用shared_ptr及其一些问题 -> 正文阅读

[开发工具]C++ std::shared_ptr:为什么使用shared_ptr及其一些问题

本文主要参考《Effective Modern C++》和《Primer C++》
为什么使用shared_ptr
在软件项目中经常碰到的一个头疼问题就是资源泄漏,或者更具体一点说内存泄漏,智能指针就是为了解决这个问题而诞生。
对于面向对象的开发语言而言,我们编写的程序中所有的对象都是有严格定义的生存周期。全局对象在程序启动时分配创建,在程序退出时销毁。对于局部临时对象,当程序进入其定义所在的作用域是被创建,离开时被销毁。局部static对象在第一次使用前分配,程序结束时销毁。对于这几种对象都是自动销毁的。
但是对于动态分配的对象,必须要显式地释放,否则就会造成资源泄漏。动态对象的正确释放是一个极其容易出错的地方。比如动态内存的使用很容易出问题,有时候会忘记释放内存而造成内存泄漏;有时则是还有其它指针引用内存的时候就释放了它,导致其它指针在使用这块内存的时候会出现问题。对于这个问题,标准库提供了智能指针来管理动态分配的对象。当一个对象应该被释放时,指向它的智能指针会自动的释放它。本文主要讲shared_ptr。

shared就是共享的意思,一个通过std::shared_ptr访问的对象其生命周期由指向它的指针们共享所有权(shared ownership)。没有特定的std::shared_ptr拥有该对象。相反,所有指向它的std::shared_ptr都能相互合作确保在它不再使用的那个点进行析构。当最后一个std::shared_ptr到达那个点,std::shared_ptr会销毁它所指向的对象。就内存回收来说,开发者不需要关心指向对象的生命周期,而对象的析构是确定性的。

std::shared_ptr通过引用计数来确保它是否是最后一个指向某种资源的指针,引用计数关联资源并跟踪有多少个std::shared_ptr指向该资源。std::shared_ptr构造函数递增引用计数值,析构函数递减值,拷贝赋值运算符可能递增也可能递减值。(如果sp1和sp2是std::shared_ptr并且指向不同对象,赋值运算符sp1=sp2会使sp1指向sp2指向的对象。直接效果就是sp1引用计数减一,sp2引用计数加一。)如果std::shared_ptr发现引用计数值为零,没有其他std::shared_ptr指向该资源,它就会销毁资源。
引用计数暗示着性能问题:
shared_ptr的一些问题

  • std::shared_ptr大小至少是原始指针的两倍,因为它内部包含一个指向资源的原始指针,还至少包含一个资源的引用计数值。shared_ptr的内存结构其实会包含一个控制块,引用计数就是在控制块中。
    在这里插入图片描述

  • 引用计数必须动态分配。
    理论上,引用计数与所指对象关联起来,但是被指向的对象不知道这件事情(不知道有指向自己的指针)。因此它们没有办法存放一个引用计数值。但是使用std::make_shared创建std::shared_ptr可以避免引用计数的动态分配,但是还存在一些std::make_shared不能使用的场景,这时候引用计数就会动态分配。

  • 由于线程安全问题(多个reader、writer可能在不同的线程),递增递减引用计数必须是原子性的。比如,指向某种资源的std::shared_ptr可能在一个线程执行析构,在另一个不同的线程,std::shared_ptr指向相同的对象,但是执行的确是拷贝操作。原子操作通常比非原子操作要慢,所以即使是引用计数,你也应该假定读写它们是存在开销的。
    std::shared_ptr构造函数并不总是递增指向对象的引用计数,因为移动构造函数的存在。从另一个std::shared_ptr移动构造新std::shared_ptr会将原来的std::shared_ptr设置为null,那意味着老的std::shared_ptr不再指向资源,同时新的std::shared_ptr指向资源。这样的结果就是不需要修改引用计数值。因此移动std::shared_ptr会比拷贝它要快:拷贝要求递增引用计数值,移动不需要。移动赋值运算符同理,所以移动赋值运算符也比拷贝赋值运算符快。

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 11:50:46  更:2022-02-26 11:54:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:55:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码