智能指针管理“newed对象”

2023-12-15 00:12

本文主要是介绍智能指针管理“newed对象”,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

为什么要有智能指针?

指针智能是管理管理动态内存分配对象的一种机制。它提供了自动管理内存,避免常见内存泄漏和悬空指针。

对于上述Func函数的操作,一不小心就会产生很多问题。

  • p1 new时候抛异常 什么都不做
  • p2 new时候抛异常 p1需要被清理
  • div除0错误 p1 p2 都需要清理

上述代码我们也实现了delete,但是却有没被调用的风险。

资源没有被回收,就会导致内存泄漏,内存越用越多,如操作系统会卡死。

自动管理资源——智能指针

RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源
        在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:

  • 不需要显式地释放资源。
  • 采用这种方式,对象所需的资源在其生命期内始终保持有效

指针智能就是针对RAII思想设计的一种管理资源的方法;


智能指针的使用

1)利用对象生命周期管理

智能指针的基本使用思路。将对象通过指针交给一个类,类在调用的时候,构造完成初始化,析构完成自动清理资源。


解决上述问题

创建对象sp1 sp2时,会调用构造函数,将new int 构造类中的指针。在sp1 sp2的生命周期结束时(栈帧的销毁)会调用对象的析构函数 ,将动态开辟的内存释放掉

new sp1异常 什么都不做 没有任何构造

new sp2 异常栈帧会跳转到catch 局部变量sp1会被销毁,调用析构

div()函数出异常 局部变量sp1和sp2的栈帧都要被销毁,自动调用析构函数

上述操作就是将一个对象托管给另一个对象管理资源。就是RAII的思想 


*和->

为了让智能指针能够像指针一样操作。我们将智能指针进行操作符重载。*(解引用)和&(取地址)。


浅拷贝问题

利用上述的指针管理资源。不适合拷贝对象。

类中对于拷贝操作默认是浅拷贝,就是将对象资源按照字节一个个拷贝过去。

对于本题中,new开辟一块空间,将空间的地址交给智能指针构造出sp1,由sp1管理资源。

而在第二步拷贝赋值中,将sp1的地址一个字节一个字节拷贝给sp2,因此二者指向同一块空间。

在对象生命周期结束时,会自动调用析构函数。sp1和sp2指向同一块空间。一块空间delete俩次,所以会产生错误。

怎么解决?

这里就从历史的角度谈谈


auto_ptr

在C++98中,提出管理权限转移的思想。

假定都是sp1做为要被覆盖的对象

  • 在拷贝构造和赋值时,将被赋值对象的资源转移到自身。
  • 在拷贝构造时-----sp2指针的地址转为空
  • 在赋值时------需要检查是否自己赋值自己!然后需要释放sp1的内存,将sp2的内存转移到sp1上

将sp2的指针悬空

由于资源管理权限被转移,指针存在悬空。

unique_ptr

在C++98和C++11之间产生了非官方库 boost

unique_ptr

简单粗暴----防止拷贝

在成员函数中,如果不写拷贝构造函数和赋值运算符,编译器就会自动生成默认函数。如果我们显示的实现,而不再赋值上操作。如果只是声明,不写实现,那么有可能在类外被实现。

因此要在类内实现声明,并且声明为私有

在C++11中,delete关键字禁止生成默认函数


三 

shared_ptr

shared_ptr 其实就是对资源做引用计数——当引用计数为 0 的时候,自动释放资源。

比如我们有俩个对象同时指向同一块空间(sp1,sp2)。如果sp1被销毁了,就会什么也不做。然后空间配套的引用计数就会从2减到1。如果当sp2也要被释放时,引用计数从1减到0,此时计数为0,就要释放这块空间。

简单的来说shared_ptr包含俩部分

  • 一个指向堆上创建的裸指针
  • 一个指向内部隐藏的、共享的管理对象 count代表被多少对象引用共享了,也就是引用对象。

计数器设为全局吗?

在C++中用全局变量要非常谨慎。

如果将计数器设为全局,那么计数器就属于全部的类,该类的任何一个对象的增加或减少,都会影响计数器。因此需要对每一块资源分配一个计数器。

  • 构造:为_pcount开空间
  • release():减计数不为0不操作,计数为0时,删除空间
  • 赋值:检查自己赋值自己,释放旧空间 更新_pcount 
  • 拷贝构造:拷贝地址和_pcount ,更新_pcount
  • 基本指针操作

循环引用的解决

shared_ptr指针还存在循环引用的问题,再下一篇文章中将作为重点探讨,同时介绍weak_ptr。

总结


1. 尽量使用智能指针管理资源申请与释放,减少人为new和delete误操作和考虑不周的问题。

2.RAII思想就是利用变量生命周期管理资源。

点我gitee提取代码

这篇关于智能指针管理“newed对象”的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/494404

相关文章

Python+PyQt5开发一个Windows电脑启动项管理神器

《Python+PyQt5开发一个Windows电脑启动项管理神器》:本文主要介绍如何使用PyQt5开发一款颜值与功能并存的Windows启动项管理工具,不仅能查看/删除现有启动项,还能智能添加新... 目录开篇:为什么我们需要启动项管理工具功能全景图核心技术解析1. Windows注册表操作2. 启动文件

gradle第三方Jar包依赖统一管理方式

《gradle第三方Jar包依赖统一管理方式》:本文主要介绍gradle第三方Jar包依赖统一管理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景实现1.顶层模块build.gradle添加依赖管理插件2.顶层模块build.gradle添加所有管理依赖包

基于Python打造一个智能单词管理神器

《基于Python打造一个智能单词管理神器》这篇文章主要为大家详细介绍了如何使用Python打造一个智能单词管理神器,从查询到导出的一站式解决,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 项目概述:为什么需要这个工具2. 环境搭建与快速入门2.1 环境要求2.2 首次运行配置3. 核心功能使用指

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

HTML5中的Microdata与历史记录管理详解

《HTML5中的Microdata与历史记录管理详解》Microdata作为HTML5新增的一个特性,它允许开发者在HTML文档中添加更多的语义信息,以便于搜索引擎和浏览器更好地理解页面内容,本文将探... 目录html5中的Mijscrodata与历史记录管理背景简介html5中的Microdata使用M

Spring 基于XML配置 bean管理 Bean-IOC的方法

《Spring基于XML配置bean管理Bean-IOC的方法》:本文主要介绍Spring基于XML配置bean管理Bean-IOC的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录一. spring学习的核心内容二. 基于 XML 配置 bean1. 通过类型来获取 bean2. 通过

Python实现word文档内容智能提取以及合成

《Python实现word文档内容智能提取以及合成》这篇文章主要为大家详细介绍了如何使用Python实现从10个左右的docx文档中抽取内容,再调整语言风格后生成新的文档,感兴趣的小伙伴可以了解一下... 目录核心思路技术路径实现步骤阶段一:准备工作阶段二:内容提取 (python 脚本)阶段三:语言风格调

Python中判断对象是否为空的方法

《Python中判断对象是否为空的方法》在Python开发中,判断对象是否为“空”是高频操作,但看似简单的需求却暗藏玄机,从None到空容器,从零值到自定义对象的“假值”状态,不同场景下的“空”需要精... 目录一、python中的“空”值体系二、精准判定方法对比三、常见误区解析四、进阶处理技巧五、性能优化

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

python uv包管理小结

《pythonuv包管理小结》uv是一个高性能的Python包管理工具,它不仅能够高效地处理包管理和依赖解析,还提供了对Python版本管理的支持,本文主要介绍了pythonuv包管理小结,具有一... 目录安装 uv使用 uv 管理 python 版本安装指定版本的 Python查看已安装的 Python