C++笔记—— 第十七篇 智能指针 C++11来了(下)

news2024/9/22 13:36:23

 

 

 

 

目录

1. 为什么需要智能指针

2. 内存泄漏

2.1 什么是内存泄漏,内存泄漏的危害

2.2 内存泄漏分类

2.3如何避免内存泄漏

3.智能指针的使用及原理

3.1 RAII

3.2 智能指针的原理

3.3 std::auto_ptr

3.4 std::unique_ptr

3.5 std::shared_ptr

shared_ptr的线程安全分为两方面:

std::shared_ptr的循环引用 

4.C++11和boost中智能指针的关系



1. 为什么需要智能指针



1. malloc出来的空间,没有进行释放,存在内存泄漏的问题。
2. 异常安全问题。如果在malloc和free之间如果存在抛异常,那么还是有内存泄漏。这种问题就叫异常安全。



2. 内存泄漏

 



2.1 什么是内存泄漏,内存泄漏的危害


 

应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死


// 1.内存申请了忘记释放

int* p1 = (int*)malloc(sizeof(int));
int* p2 = new int;

// 2.异常安全问题
int* p3 = new int[10];
Func(); // 这里Func函数抛异常导致 delete[] p3未执行,p3没被释放.
delete[] p3;


2.2 内存泄漏分类



C/C++程序中一般我们关心两种方面的内存泄漏:


堆内存泄漏(Heap leak)


堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存,用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放,那么以后这部分空间将无法再被使用,就会产生Heap Leak。


系统资源泄漏


指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。 



2.3如何避免内存泄漏



1. 工程前期良好的设计规范,养成良好的编码规范,申请的内存空间记着匹配的去释放。ps:这个理想状态。但是如果碰上异常时,就算注意释放了,还是可能会出问题。需要下一条智能指针来管理才有保证。
2. 采用RAII思想或者智能指针来管理资源。
3. 有些公司内部规范使用内部实现的私有内存管理库。这套库自带内存泄漏检测的功能选项。
4. 出问题了使用内存泄漏工具检测。


总结

内存泄漏非常常见,解决方案分为两种:

1、事前预防型。如智能指针等。

2、事后查错型。如泄漏检测工具。 



3.智能指针的使用及原理




3.1 RAII


利用对象生命周期来控制程序资源

在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:
不需要显式地释放资源。
采用这种方式,对象所需的资源在其生命期内始终保持有效


3.2 智能指针的原理


智能指针的原理:
1. RAII特性
2. 重载operator*和opertaor->,具有像指针一样的行为

 


3.3 std::auto_ptr


C++98版本的库中就提供了auto_ptr的智能指针

#include <memory>

// auto_ptr的问题:当对象拷贝或者赋值后,前面的对象就悬空了
// C++98中设计的auto_ptr问题是非常明显的,所以实际中很多公司明确规定了不能使用auto_ptr 


3.4 std::unique_ptr


C++11中开始提供更靠谱的unique_ptr

unique_ptr的设计思路非常的粗暴-防拷贝,也就是不让拷贝和赋值

private:
// C++98防拷贝的方式:只声明不实现+声明成私有
UniquePtr(UniquePtr<T> const &);
UniquePtr & operator=(UniquePtr<T> const &);


// C++11防拷贝的方式:delete
UniquePtr(UniquePtr<T> const &) = delete;
UniquePtr & operator=(UniquePtr<T> const &) = delete; 


3.5 std::shared_ptr



C++11中开始提供更靠谱的并且支持拷贝的shared_ptr 

shared_ptr通过引用计数支持智能指针对象的拷贝 

1. shared_ptr在其内部,给每个资源都维护了着一份计数,用来记录该份资源被几个对象共享。
2. 在对象被销毁时(也就是析构函数调用),就说明自己不使用该资源了,对象的引用计数减一。
3. 如果引用计数是0,就说明自己是最后一个使用该资源的对象,必须释放该资源;
4. 如果不是0,就说明除了自己还有其他对象在使用该份资源,不能释放该资源,否则其他对象就成野指针了。 

 

shared_ptr的线程安全分为​​​​​​​两方面:

1. 智能指针对象中引用计数是多个智能指针对象共享的,两个线程中智能指针的引用计数同时++或--,这个操作不是原子的,引用计数原来是1,++了两次,可能还是2。这样引用计数就错乱了。会导致资源未释放或者程序崩溃的问题。所以智能指针中引用计数++、--是需要加锁的,也就是说引用计数的操作是线程安全的。
2. 智能指针管理的对象存放在堆上,两个线程中同时去访问,会导致线程安全问题。

 

std::shared_ptr的循环引用 

 当两个智能指针互相指向对方,会形成循环引用,谁也不会释放

解决方案:在引用计数的场景下,把节点中的_prev和_next改成weak_ptr就可以了
// 原理就是,node1->_next = node2;和node2->_prev = node1;时weak_ptr的_next和_prev不会增加node1和node2的引用计数 



4.C++11和boost中智能指针的关系




1. C++ 98 中产生了第一个智能指针auto_ptr.
2. C++ boost给出了更实用的scoped_ptr和shared_ptr和weak_ptr.
3. C++ TR1,引入了shared_ptr等。不过注意的是TR1并不是标准版。
4. C++ 11,引入了unique_ptr和shared_ptr和weak_ptr。需要注意的是unique_ptr对应boost的
scoped_ptr。并且这些智能指针的实现原理是参考boost中的实现的。 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/511174.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JVM性能调优

一、JVM内存模型及垃圾收集算法 1.根据Java虚拟机规范&#xff0c;JVM将内存划分为&#xff1a; New&#xff08;年轻代&#xff09; Tenured&#xff08;年老代&#xff09; 永久代&#xff08;Perm&#xff09; 其中New和Tenured属于堆内存&#xff0c;堆内存会从JVM启动参…

【牛客刷题专栏】0x28:JZ30 包含min函数的栈(C语言编程题)

前言 个人推荐在牛客网刷题(点击可以跳转)&#xff0c;它登陆后会保存刷题记录进度&#xff0c;重新登录时写过的题目代码不会丢失。个人刷题练习系列专栏&#xff1a;个人CSDN牛客刷题专栏。 题目来自&#xff1a;牛客/题库 / 在线编程 / 剑指offer&#xff1a; 目录 前言问…

【神经网络】tensorflow实验9--分类问题

1. 实验目的 ①掌握逻辑回归的基本原理&#xff0c;实现分类器&#xff0c;完成多分类任务&#xff1b; ②掌握逻辑回归中的平方损失函数、交叉熵损失函数以及平均交叉熵损失函数。 2. 实验内容 ①能够使用TensorFlow计算Sigmoid函数、准确率、交叉熵损失函数等&#xff0c…

(浙大陈越版)数据结构 第二章 线性结构 2.4 多项式的加法和乘法运算实现

目录 2.4.1多项式的加法运算实现 如何设计一个函数分别求两个一元多项式的和&#xff1f; 算法思路&#xff1a;两个指针p1&#xff0c;p2分别指向两个多项式的第一个结点&#xff08;最高项&#xff09;并循环 循环&#xff1a; 2.4.2 多项式的乘积 1.多项式的表示 2.程…

IPsec VPN IKE方式协商密钥

实验拓扑 要求pc1与pc2两个网络访问走ipsec隧道互访。 前言&#xff1a; ipsecs 隧道两端的acl规则定义的协议类型要一致&#xff0c;如果一端是ip协议&#xff0c;另一端也必须是ip协议 配置acl的原因是&#xff1a;1&#xff0c;通过acl&#xff08;permit&#xff09;指定需…

Metalama released Crack

Metalama released Crack Metalama是一个面向C#的元编程框架。它可以帮助您提高代码质量和生产力。使用Metalama&#xff0c;您可以通过在编译过程中动态生成样板文件来减少样板文件。您的源代码仍然非常清晰。根据体系结构、模式和约定实时验证代码。无需等待代码评审。通过定…

React从入门到实战 - React初体验

文章目录 特点相关JS库步骤准备步骤操作步骤 关于虚拟DOMJSX语法规则函数式组件常见的几种错误正确写法 类式组件 特点 采用组件化模式&#xff0c;声明式编程&#xff0c;提高开发效率及组件复用率在React Native 中使用React语法进行移动端开发使用虚拟DOM优秀的Diffing算法…

Java8 map.getOrDefault()你真的了解吗

大家好&#xff0c;我是三叔&#xff0c;很高兴这期又和大家见面了&#xff0c;一个奋斗在互联网的打工人。 map.getOrDefault()方法 在Java编程中&#xff0c;Map是一种非常常用的数据结构。Map通常用于存储键值对&#xff0c;其中每个键映射到一个值。当我们尝试访问一个不…

文件一直处于修改状态 git checkout 无法还原的问题解决方法

问题描述 最近在 RT-Thread 时&#xff0c;使用 Git 回退版本验证问题&#xff0c;后来 git pull 拉取最新代码后&#xff0c;发现里面有几个文件&#xff0c;一直为【修改】状态&#xff0c;并且无法还原&#xff0c;git checkout xxx git reset --hard 都用了&#xff0c;依旧…

基于AT89C51单片机的温度控制系统报警器

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/87771724?spm1001.2014.3001.5503 源码获取 单片机读取温度传感器当前的温度值并在LCD液晶显示屏上的第一行显示当前的温度值&#xff0c;单片机读取按键状态并通过…

Flask框架之异常处理、请求钩子、上下文的使用

Flask框架之异常处理、请求钩子、上下文的使用 异常处理捕获指定异常状态码捕获指定异常类型抛出HTTP Exception 请求钩子概述基本使用 请求上下文概述应用上下文current_app对象g对象 请求上下文request对象session对象 异常处理 捕获指定异常状态码 可以使用app.errorhandle…

Github的使用

1.基本概念&#xff1a; 仓库&#xff08;Repository&#xff09;:仓库用来存放项目代码&#xff0c;每个项目对应一个仓库&#xff0c;多个开源项目则有多个仓库 收藏&#xff08;Star&#xff09;:收藏项目&#xff0c;方便下次查看 复制克隆项目:&#xff08;Fork&#x…

JVM类加载、类变量初始化顺序

题目 先来看一个题目&#xff0c;以下程序的输出结果是什么 运行结果 关于类加载机制 关于JVM的类加载 《深入理解Java虚拟机》中关于类加载是这样说的&#xff1a; Java虚拟机把描述类的数据从Class文件加载到内存&#xff0c;并对数据进行校验、转换解析和初始化&#x…

【SLAM学习】基于Pangolin绘制运动轨迹

Pangolin是一个轻量级的跨平台视图控制库&#xff0c;主要用于可视化、交互和调试三维数据。该库提供了一系列图形界面工具&#xff0c;包括窗口、OpenGL渲染器、3D相机、图像显示等&#xff0c;可以方便地进行三维数据可视化和交互。 Pangolin库的主要特点如下&#xff1a; 轻…

SpringBoot的多配置文件

文章目录 1.配置文件的命名规则2.配置文件选择3.配置文件的优先级 1.配置文件的命名规则 配置文件一般要求以application开头&#xff0c;可以是.yml结尾的文件&#xff0c;也可以是.properties结尾的文件。 2.配置文件选择 当有多个配置文件&#xff0c;需要指定其中一个生…

关于C语言取余运算的那些大坑

0.前言 您好&#xff0c;这里是limou3434的一篇个人博文&#xff0c;感兴趣的话您也可以看看我的其他文章&#xff0c;本次我想给您带来的是关于C语言操作符‘%’的一些奇怪现象以及背后的原理解释&#xff0c;本章用了一点点python语法&#xff08;比如在python中“//”是整除…

C++开发环境的搭建-Windows:VSCode+mingw64+CMake

文章目录 一、软件安装1. 网址及下载的软件2. VSCode中配置关于C的最简插件&#xff1a; 二、C调试环境的编译要求1. 在编译时要带-g参数2. 多文件编译需要分步编译 三、VSCode的调试配置如下&#xff1a;1. 单文件调试设置4. 多文件调试设置 一、软件安装 1. 网址及下载的软件…

【JavaEE进阶】——第六节.第一个MyBatis程序

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;JavaEE进阶 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01; 文章目录 前…

计算机视觉(5)—— 图像分类

目录 五、图像分类 5.1 AlexNet 5.2 VGG 5.3 GoogLeNet、Inception 5.3.1 Inception V1 5.3.2 Inception V2 5.3.3 Inception V3 5.3.4 Inception V4 5.4 ResNet 残差网络 5.4.1 ResNet 5.4.2 ResNeXt 5.5 CNN设计准则 五、图像分类 5.1 AlexNet 5.2 VGG 5.3 Go…

【剑指 Offer】05,替换字符创中的空格;难度等级:简单。易错点:C++中 char 和 string 类型的转换

【剑指 Offer】05&#xff0c;替换字符创中的空格&#xff1b;难度等级&#xff1a;简单。 文章目录 一、题目二、题目背景三、我的解答四、易错点五、知识点&#xff1a;char 和 string 类型的转换 一、题目 二、题目背景 在网络编程中&#xff0c;如果 URL 参数中含有特殊字…