首页 > 编程语言 >深入理解C++智能指针系列(一)

深入理解C++智能指针系列(一)

时间:2024-05-25 22:34:13浏览次数:27  
标签:释放 管理 RAII C++ 智能 内存 分配 指针

引言

都知道C/C++的最难的就是需要程序员自己管理内存,往往会因为一个简单的逻辑错误导致内存管理异常。
通常内存管理过程中会遇到以下问题:

  1. 内存泄漏

当开发者忘记释放已分配的内存时,就会发生内存泄漏。这种情况在大型项目中非常常见,项目中存在大量动态内存操作时,很容易遗漏释放操作。

  1. 空悬指针

当一个指针被释放后继续被使用,它就变成了空悬指针。这种指针指向已被释放的内存,继续使用这种指针会导致不可预测的行为和程序崩溃。

  1. 双重释放

如果同一个内存地址被释放多次,会发生双重释放错误,这可能导致程序崩溃或其他问题。

  1. 不匹配的分配/释放

使用new分配内存时应该使用delete来释放,对于使用new[]分配的数组应该用delete[]来释放。如果这些操作不匹配,也会导致不可预测的行为或崩溃。

正文

为了减轻程序员对内存管理的难度和负担,C++11引入了智能指针。
本文作为智能指针的第一篇,将从内存管理的基础来逐渐深入介绍智能指针。

栈内存和堆内存

和其他语言一样,C++有多重类型的内存,它们对应于物理内存的不同部分,分别是:静态、栈、堆。
静态内存是一个非常复杂的话题,这里不过多关注,我们主要关注栈内存和堆内存。

栈内存

栈是一种遵循后进先出(LIFO,Last In First Out)原则的数据结构,用于存储局部变量和函数调用的信息。

特点
  • 速度快:栈内存的分配和回收速度非常快。内存分配简单,因为它只涉及指针的移动。
  • 自动管理:函数执行完毕后,栈帧会自动弹出,局部变量也随之被销毁,程序员不需要手动管理这部分内存。
  • 空间限制:栈的大小通常有限,并且由操作系统预先定义。因此,大量数据或者不确定大小的数据不适合在栈上分配。
限制
  • 由于空间有限,大型数据结构不应该存储在栈内存中,避免栈溢出
  • 栈内存中的数据不能被随意地访问或返回给函数外部,因为它们在函数返回后就不再存在了

堆内存

堆内存是一个用于动态内存分配的区域,程序在运行时可以从堆中分配或释放内存。与栈内存不同,堆内存的使用没有固定的模式,分配和释放顺序可以不一致。

特点
  • 灵活性:堆允许程序动态地分配和释放内存,非常适合存储生命周期不确定或大小可变的数据对象。
  • 容量大:相比栈内存,堆的大小通常只受可用系统内存的限制。
  • 手动管理:程序员负责分配和释放堆内存。这提供了使用灵活性,但也增加了错误发生的风险,如内存泄漏或指针错误。
缺点
  • 管理复杂:需要程序员显式地管理内存,易出错。
  • 效率较低:相比栈内存的操作,堆内存分配和回收的成本较高,因为涉及到更复杂的内存管理和可能的碎片化问题。
  • 安全性问题:不当的内存管理可能导致安全漏洞,如缓冲区溢出和无效指针访问。

RAII

RAII(Resource Acquisition Is Initialization)是一种编程中的设计模式,用于在面向对象的编程中管理资源(如内存、文件句柄、网络连接等)的生命周期。这个模式通过确保资源的获取与对象的生命周期同步,从而实现资源的自动管理,主要目的是减少内存泄漏和资源泄漏的风险。

RAII的核心原则

  1. 资源封装在对象中

RAII 模式通过将资源封装在拥有确定生命周期的对象中来管理资源。资源的分配(获取)发生在对象的构造过程中,而资源的释放发生在对象的析构过程中。

  1. 自动资源管理

利用 C++ 的构造函数和析构函数,RAII确保只要对象还在作用域内,其管理的资源就会被正确维护,并在对象生命周期结束时自动释放。这消除了手动释放资源的需求,减少了因遗忘释放资源而导致的内存泄漏。

  1. 异常安全保证

RAII 也增强了代码的异常安全性,因为当异常发生时,局部对象会按照构造的逆序自动销毁,其析构函数将被调用以释放资源,从而防止资源泄露。

智能指针正是应用了RAII的设计模式来实现自动管理内存。

标签:释放,管理,RAII,C++,智能,内存,分配,指针
From: https://blog.csdn.net/LeoLei8060/article/details/139204803

相关文章

  • Ubuntu16.04 opencv环境搭建(C++)
    Ubuntu下vscode跑opencv程序环境搭建。目录1ubuntu查看opencv版本2下载opencv包3依赖配置4进入安装包内执行5配置环境变量6VScode配置-下载c++扩展7编译运行helloworld8在vscode中配置opencv环境9运行结果1ubuntu查看opencv版本pkg-config--modversion......
  • 【精品毕设推荐】基于Springboot的智能物流管理系统设计与实现
    点击下载原文及代码,可辅助在本地配置运行摘要随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了智能物流管理系统的开发全过程。通过分析智能物流管理系统管理的不足,创建了一个计算机管理智能物流管理系统的方案。文章介绍了智能......
  • C++初阶学习第九弹——探索STL奥秘(四)——vector的深层挖掘和模拟实现
    string(上):C++初阶学习第六弹——探索STL奥秘(一)——标准库中的string类-CSDN博客string(下):C++初阶学习第七弹——探索STL奥秘(二)——string的模拟实现-CSDN博客vector(上):C++初阶学习第八弹——探索STL奥秘(三)——深入刨析vector的使用-CSDN博客前言:在前面我们已经学习了string的......
  • 基于51单片机智能大棚浇花花盆浇水灌溉补光散热设计
    一.硬件方案本设计通过光敏电阻检测光照强度,然后A/D模块PCF8591处理后,将光照强度值实时显示在液晶上,并且可以按键控制光照的强度值,当光照低于设定的阈值,1颗白色高亮LED灯亮进行补光,光照高于设定的阈值,就不用管。通过DS18B20检测温度值,并且实时显示在1602液晶上,并且可以通过......
  • 认识认识指针(2)
    1.数组名的理解数组名和数组⾸元素的地址打印出的结果⼀模⼀样,数组名就是数组⾸元素(第⼀个元素)的地址。其实数组名就是数组⾸元素(第⼀个元素)的地址是对的,但是有两个例外:•sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩,单位是字......
  • 初识指针(1)
    1.内存和地址1.1内存把内存划分为⼀个个的内存单元,每个内存单元的⼤⼩取1个字节。计算机中常⻅的单位(补充):⼀个⽐特位可以存储⼀个2进制的位1或者0。1byte=8bit1KB=1024byte1MB=1024KB1GB=1024MB1TB=1024GB1PB=1024TB其中,每个内存单元,相当于⼀个学⽣宿......
  • Ncast高清智能录播系统存在任意文件读取漏洞以及busiFacade RCE漏洞
    漏洞描述由于系统对用户输入的文件路径未进行充分验证,允许用户输入任意文件路径,导致存在任意文件读取漏洞,攻击者可以利用该漏洞获取系统配置文件、密码文件等。该系统的/classes/common/busiFacade.php接口存在RCE漏洞,攻击者可以利用此漏洞执行任意命令。fofaapp="Ncast-产品"......
  • C++入门(3) 指针和引用的区别|引用的本质|引用小结|inline函数|缺省函数
    一,引用引用和指针的区别1,从语法规则上讲指针变量存储某个实例(变量或者对象)的地址;引用是某个实例的别名程序为指针变量分配内存空间;不为引用分配内存空间指针变量的值可以改变;引用一旦初始化就无法改变指针变量可以为NULL;但是没有空引用指针作为形参需要判断是否为空;引用......
  • 《拯救大学生课设不挂科第二期之Windows11下安装VC6.0(VC++6.0)与跑通Hello World C语言
    背景与目标人群:大学第一次学C语言的时候,大部分老师会选择VC6这个编辑器。但由于很多人是新手,第一次上大学学C语言。老师要求VC6.0(VC++6.0)写C语言跑程序可能很多人还是第一次接触电脑。需要安装VC6这个编辑器并且编译C语言程序,但是不怎么会装。博主结合自己当时学习与现在......
  • c++实现简单算法【1】
    1.交换两数inta=2,b=3;inttemp=a;a=b;b=a; 函数包装指针#include<stdio.h>#include<string.h>//#include<iostream>//usingnamespacestd;voidswap(int*a,int*b){ inttemp=*a; *a=*b;//修改a指针指向的地址的对应的变量的值,地址不变 *b=temp;}int......