C++智能指针的分析与使用

【C++】智能指针 为什么需要智能指针呢?有了智能指针带来了什么问题?库里是如何解决的?就不得不说智能指针发展的历史。auto_ptr的解决方法、unique_ptr解决方法、shared_ptr解决方法。shared_ptr线程安全问题、循环引用问题。还有定制删除器。 阅读详情

手动管理的弊端

在简单的程序中,我们不大可能忘记释放 new 出来的指针,但是随着程序规模的增大,我们忘了 delete 的概率也随之增大。在 C++ 中 new 出来的指针,赋值意味着引用的传递,当赋值运算符同时展现出“值拷贝”和“引用传递”两种截然不同的语义时,就很容易导致“内存泄漏”。

手动管理内存带来的更严重的问题是,内存究竟要由谁来分配和释放呢?指针的赋值将同一对象的引用散播到程序各处,但是该对象的释放却只能发生一次。当在代码中用完了一个资源指针,该不该释放 delete 掉它?这个资源极有可能同时被多个对象拥有着,而这些对象中的任何一个都有可能在之后使用该资源,其余指向这个对象的指针就变成了“野指针”;那如果不 delete 呢?也许你就是这个资源指针的唯一使用者,如果你用完不 delete,内存就泄漏了。

资源的拥有者是系统,当我们需要时便向系统申请资源,当我们不需要时就让系统自己收回去(Garbage Collection)。当我们自己处理的时候,就容易出现各种各样的问题。

C++ 中的智能指针

为了让用户免去手动 delete 资源的烦恼,不少类库采用了 RAII 风格,即 Resource Acquisition Is Initialization(资源获取即初始化)。这种风格采用类来封装资源,在类的构造函数中获取资源,在类的析构中释放资源,这个资源可以是内存,可以是一个网络连接。

智能指针就是 C++ RAII 的一种应用,是存储指向动态分配对象指针的类。智能指针在面对异常的时候格外有用,因为它们能在适当的时间删除所指向的对象(可以了解一下异常安全)。C++ 中的智能指针首先出现在 boost 中,随着使用的人越来越多,C++11 也已经引入了智能指针来管理动态对象。C++11 主要提供了 shared_ptr、unique_ptr、weak_ptr 三种不同类型的智能指针。

shared_ptr

智能指针是(几乎总是)模板类,shared_ptr 同样是模板类,所以在创建 shared_ptr 时需要指定其指向的类型。shared_ptr 负责在不使用实例时释放由它管理的对象,同时它可以自由的共享它指向的对象。

shared_ptr 使用经典的“引用计数”的方法来管理对象资源。引用计数指的是,所有管理同一个裸指针( raw pointer )的 shared_ptr,都共享一个引用计数器,每当一个 shared_ptr 被赋值(或拷贝构造)给其它 shared_ptr 时,这个共享的引用计数器就加1,当一个 shared_ptr 析构或者被用于管理其它裸指针时,这个引用计数器就减1,如果此时发现引用计数器为0,那么说明它是管理这个指针的最后一个 shared_ptr 了,于是我们释放指针指向的资源。

在底层实现中,这个引用计数器保存在某个内部类型里(这个类型中还包含了 deleter,它控制了指针的释放策略,默认情况下就是普通的delete操作),而这个内部类型对象在 shared_ptr 第一次构造时以指针的形式保存在 shared_ptr 中(所以一个智能指针的析构会影响到其他指向同一位置的智能指针)。shared_ptr 重载了赋值运算符,在赋值和拷贝构造另一个 shared_ptr 时,这个指针被另一个 shared_ptr 共享。在引用计数归零时,这个内部类型指针与 shared_ptr 管理的资源一起被释放。此外,为了保证线程安全性,引用计数器的加1,减1操作都是原子操作,它保证 shared_ptr 由多个线程共享时不会爆掉。

对于 shared_ptr 在拷贝和赋值时的行为,《C++Primer第五版》中有详细的描述:

每个 shared_ptr 都有一个关联的计数值,通常称为引用计数。无论何时我们拷贝一个 shared_ptr,计数器都会递增。
例如,当用一个 shared_ptr 初始化另一个 shred_ptr,或将它当做参数传递给一个函数以及作为函数的返回值时,它所关联的计数器就会递增。当我们给 shared_ptr 赋予一个新值或是 shared_ptr 被销毁(例如一个局部的 shared_ptr 离开其作用域)时,计数器就会递减。一旦一个 shared_ptr 的计数器变为0,它就会自动释放自己所管理的对象。

下面看一个常见用法,包括:
1. 创建 shared_ptr 实例 2. 访问所指对象 3. 拷贝和赋值操作 4. 检查引用计数。更多的用法请自行查阅。

/*
 * @filename:    shared_ptr.cpp
 * @author:      Tanswer
 * @date:        2018年01月10日 19:40:45
 * @description:
 */

#include <iostream>
#include <string>
#include <memory>
using namespace std;

class Test{
public:
    Test(string name){
        name_ = name;
        cout << this->name_ << "  constructor" << endl;
    }
    ~Test(){
        cout << this->name_ << "  destructor" << endl;
    }

    string name_;
};


int main()
{
    /* 类对象 原生指针构造 */
    shared_ptr<Test> pStr1(new Test("object"));
    cout << (*pStr1).name_ << endl;
    /* use_co
Bulk / Smart-seq2数据分析一般流程 Bulk RNA-seq(RNA-Seq of bulk samples)是一种RNA-Seq技术应用,它是通过将整个组织或细胞群体的RNA提取并混合,进行高通量测序来分析基因表达的技术。转录本定量结果可以用于后续的差异表达分析和聚类分析。功能注释和富集分析:对差异表达基因进行功能注释和富集分析,以帮助理解差异表达基因的功能和调控网络,从而获得对研究样品的更深入的理解。数据可视化:最后,将聚类分析的结果进行可视化,可以使用常见的数据可视化工具,如ggplot2、Plotly等,来帮助用户更好地理解数据。 阅读详情

相关推荐

VisionPro 9.0 QuickBuild里用C#脚本调用Halcon 23.11模型,保姆级图文配置流程

本文详细介绍了如何在VisionPro 9.0 QuickBuild环境中使用C#脚本调用Halcon 23.11深度学习模型,提供从环境配置到模型集成的保姆级图文教程。重点解决图像格式转换、许可证配置等工业视觉检测中的常见问题,帮助开发者快速实现高效、稳定的视觉检测流水线部署。

weixin_27027459的博客 432

阿里开源最强数字人工具 EchoMimicV2,本地部署(一)

EchoMimicV2是阿里推出的半身人体AI数字人项目,基于参考图片、音频剪辑和手部姿势序列生成高质量动画视频,确保音频内容与半身动作的一致性。现在本地部署,安装体验一下。

缘分天空的专栏 4614

Unity如何实现数字人口型同步

SALSA LipSync v2是一款实时唇音同步系统,无需音素映射即可根据音频自动生成口型动画。系统提供三大核心功能:基于音频波形分析的智能口型同步、EmoteR表情随机化工具以及Eyes眼睛/头部追踪系统。配置流程简单快捷,只需导入模型后通过一键配置完成基础设置,再添加A/E/I/O/U等基本口型混合变形即可实现基础功能。进阶功能支持表情池管理(手动/随机/强调/重复触发)和眼部动作配置(骨骼旋转或混合变形)。系统支持三种输入方式:本地音频文件分析、麦克风实时输入和文本转语音,为数字人角色提供完整的表情

TxNet 759

知识图谱-KGE-语义匹配-双线性模型-2018:SimplE

【paper】 SimplE Embedding for Link Prediction in Knowledge Graphs 【简介】 本文是加拿大英属哥伦比亚大学的两位学者发表在 NIPS 2018 上的工作,文章提出了 SimplE(Simple Embedding)。这篇和前面一篇差不多,也是对 1927 年的 CP 进行改进(简化),传统CP为实体分配的两个向量是独立训练的,SimplE利用关系的逆在三元组打分函数中加上了一个对称项,使得每个实体的两个向量依赖学习,并且 SimplE 的复杂度随

u013250861的博客 957

52、基于格的具有解密密钥暴露抗性的可撤销(分层)身份基加密方案

本文提出了首个基于格的具有解密密钥暴露抗性(DKER)的可撤销分层身份基加密(RHIBE)方案。通过引入分层密文、分层解密密钥和级别转换密钥等创新工具,克服了格结构与传统密钥重新随机化属性不匹配的难题。该方案不仅支持可扩展的密钥撤销机制,还具备密钥委托功能,为后量子密码学领域的发展提供了新的思路和方法。

efc12345678的博客 123

2026华数杯 国际大学生数学建模竞赛 A题 如何防守直接任意球? 解题思路+模型分析+代码

2026华数杯 国际大学生数学建模竞赛 A题 如何防守直接任意球? 解题思路+模型分析+代码。基于视频数据重构进球轨迹,建立空间坐标系并进行曲线拟合,推算初始速度。建立"香蕉球"、"电梯球"、"落叶球"三种典型直接任意球轨迹的动力学模型,分析C罗进球的类型。针对C罗这类强力球员的直接任意球,提出人墙排布策略和守门员防守策略。

YOLO 663

基于PCL、Open3d、Easy3d 、VTK等常见开源库的QT开发

PCL+QT开发

阁楼 2万+

手把手教你在飞牛 NAS 上部署自有图床,含Python调用接口

📸 想在飞牛 NAS 上部署图床?这篇教程超适合小白!从安装到使用,步骤清晰~

XiaoqiangClub的博客 2344

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

上一篇: Muduo网络库源码分析之对socket及其相关操作的封装
下一篇: Muduo网络库源码分析之Acceptor和TcpServer
Tanswer_
博客等级 码龄11年 231粉丝 91原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值