C++学习:动态内存

2023-11-13

动态内存

静态内存用来保存局部static对象、类static数据成员、定义在任何函数之外的变量。static对象在使用之前分配,在程序结束后销毁。

栈内存用来保存定义在函数内的非static对象。对于栈对象,仅在其定义的程序块运行时才存在。

对于分配在静态或栈内存中的对象由编译器自动创建和销毁。

动态内存用来存储动态分配的对象,程序在运行时分配的对象,动态对象的生存期由程序来控制,当不再使用时,必须显式地销毁它们。

在C++中,动态内存的管理是一对运算符完成的:new和delete。

  1. new:在动态内存中为对象分配控件并返回一个指向该对象的指针;
  2. delete:接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。
动态内存管理经常会出现两种问题:
  1. 忘记释放内存,造成内存泄漏
  2. 尚有指针引用内存的情况下就释放了该内存,造成引用非法内存
  3. 同一块内存释放两次,第一次delete正常释放空间,第二次delete将可能破坏自由空间。

为了更加容易、安全地使用动态内存,新的标准库引入了智能指针。智能指针的行为类似常规指针,重要的区别在于智能指针负责自动释放所指向的对象

智能指针

智能指针是一个类,用来存储指向动态分配对象的指针,负责自动释放动态分配的对象,防止堆内存泄露。动态分配的资源,交给一个类对象去管理,当类对象声明周期结束时,自动调用析构函数释放资源。智能指针包含在头文件****中。

shared_ptr

允许多个指针指向同一个对象;该类型智能指针在实现上采用 引用计数机制,每当多一个指针指向该对象时,指向该对象的所有智能指针内部的引用计数加1,当有一个shared_ptr指针放弃了堆内存的“使用权”,引用计数减1,此时并不影响其他指向同一堆内存的shared_ptr指针,只有引用计数为0时,堆内存才会被释放。

  • 智能指针将一个计数器与类指向的对象相关联,引用计数器跟踪共有多少个类对象共享同意指针;
  • 每次创建类的新对象时,初始化指针并将引用计数置为1;
  • 当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;
  • 对一个对象进行赋值时,赋值操作符减少左操作数所指向的引用计数(如果引用计数减至0,则删除对象),并增加右操作数所指对象的引用计数;
  • 调用析构函数时,构造函数减少引用计数,若引用计数减为0,则删除基础对象。

shared_ptr和unique_ptr都支持的操作

shared_ptr sp 空智能指针,可以指向类型为T的对象
unique_ptr up 空智能指针,可以指向类型为T的对象
p 将p用作一个条件判断,若p指向一个对象,则为true。
*p 解引用p,获得它指向的对象
p->mem 等价于(*p).mem
p.get() 返回p中保存的指针,若智能指针释放了其对象,返回的指针所指向的对象也就消失了
swap(p, q) 交换p和q中的指针
p.swap(q) 交换p和q中的指针

shared_ptr独有的操作

make_shared(args) 返回一个shared_ptr,指向 一个动态分配的类型为T的对象,使用args初始化此对象
shared_ptrp(q) p是shared_ptr q的拷贝;此操作会递增q中的计数器。q中的指针必须能转化为T*。
p = q p和q都是shared_ptr,所保存的指针必须能相互转换。此操作会递减p的引用计数,递增q的引用计数;若p的引用计数为0,则将其管理的原内存释放。
p.unique() 若p.use_count()为1,返回true;否则返回false
p.use_count() 返回与p共享对象的智能指针数量,可能很慢,主要用于调试
shared_ptr<string> p1;
shared_ptr<int> p2 = make_shared<int>(42);
auto p3 = make_shared<vector<int>>();

unique_ptr

独占所指向的对象,采用独享所有权语义,一个非空的unique_ptr总是拥有它所指向的资源。
转移一个unique_ptr将会把所有权全部从源指针转移给目标指针,源指针被置空;所以unique_ptr不支持普通的拷贝和赋值操作不能用在STL容器中;如果对一个unique_ptr进行拷贝,那么拷贝结束后,这两个unique_ptr都会指向相同的资源,造成在结束时对同一内存指针多次释放而导致程序崩溃。

unique_ptr的操作

unique_ptr u1 空unique_ptr,可以指向类型为T的对象。u1会使用delete来释放它的指针;u2会使用一个类型为D的可调用对象来释放它的指针。
unique_ptr<T, D> u2
unique_ptr<T, D> u(d) 空unique_ptr,指向类型为T的对象,用类型为D的对象d代替delete
u = nullptr 释放u指向的对象,将u置为空
u.release() u放弃对指针的控制权,返回指针,将u置空
u.reset() 释放u指向的对象
u.reset(q) 如果提供了内置指针q,令u指向这个对象;否则将u置空
u.reset(nullptr) 将u置空

weak_ptr

弱引用。引用计数机制会存在一个问题:互相引用成环,即环形引用,这样两个指针指向的内存都无法释放,需要使用weak_ptr打破环形引用。
weak_ptr作为弱引用,是为了配合shared_ptr而引入的一种智能指针,它指向一个由shared_ptr管理的对象而不影响所指对象的生命周期,即只引用不计数
如果一块内存被shared_ptr和weak_ptr同时引用,当所有shared_ptr析构了之后,不管还有没有weak_ptr引用该内存,内存也会被释放,所以weak_ptr不保证它指向的内存一定是有效的,在使用前使用函数lock()检查weak_ptr是否为空指针。

weak_ptr的操作

weak_ptr w 空weak_ptr,可以指向类型为T的对象。
weak_ptr w(sp) 与shared_ptr sp指向相同对象的weak_ptr。T必须能转换为sp指向的类型。
w = p p可以是一个shared_ptr或一个waek_ptr。赋值后w与p共享对象。
w.reset() 将w置空
w.use_count() 与w共享对象的shared_ptr的数量
w.expired() 若w.use_count()为0,返回true,否则返回false。
w.lock() 如果expired为true,返回一个空shared_ptr;否则返回一个指向w的对象的shared_ptr。

auto_prt

主要是为了解决“有异常抛出时发生内存泄露”的问题,发生异常而无法正常释放内存。
auto_ptr有拷贝语义,拷贝后源对象变得无效,这可能引发很严重的问题;而unique_ptr无拷贝语义,但提供了移动语义,这样的错误不再发生。
auto_ptr不支持拷贝和赋值操作,不能用在STL标准容器中,因为STL容器中的元素经常要支撑拷贝、赋值操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++学习:动态内存 的相关文章

  • 无法在 QGLWidget 中设置所需的 OpenGL 版本

    我正在尝试在 Qt 4 8 2 中使用 QGLWidget 我注意到 QGLWidget 创建的默认上下文不显示 OpenGL 3 1 以上的任何输出 Qt wiki 有一个教程 http qt project org wiki How t
  • 如何使用C从http下载文件?

    最近几天我试图弄清楚如何从 URL 下载文件 这是我对套接字的第一个挑战 我用它来了解协议 所以我想在没有 cURL 库的情况下只用 C 语言来完成它 我搜索了很多 现在我可以打印页面的源代码 但我认为这与文件不同 我不必只将接收到的数据从
  • 与 MinGW 的静态和动态/共享链接

    我想从一个简单的链接用法开始来解释我的问题 假设有一个图书馆z它可以编译为共享库 libz dll D libs z shared libz dll 或静态库 libz a D libs z static libz a 让我想要链接它 然后
  • 使用 POST 的 HttpWebRequest 的性能

    我有一个用于测试网络服务的小工具 它可以使用 POST 或 GET 调用 Web 服务 使用POST的代码是 public void PerformRequest WebRequest webRequest WebRequest Creat
  • 如何使用T4从一个模板同时生成两个文件?

    我遇到的情况是 我需要生成两个 CSharp 代码文件 它们的代码几乎相同 但方法的输入和输出类型的命名空间不同 事实上 每个文件都针对特定国家 地区 并且类型来自特定国家 地区的 WSDL 我正在围绕服务编写一些包装器 逻辑完全相同 但从
  • 如何在 C++ 中为指针“this”赋值

    在函数中 如何分配this一个新的价值 您可以分配对象this点于 this XY 但你不能分配直接值this this XY Error Expression is not assignable
  • 用于 C++ 中图像分析的 OpenCV 二进制图像掩模

    我正在尝试分析一些图像 这些图像的外部周围有很多噪声 但内部有一个清晰的圆形中心 中心是我感兴趣的部分 但外部噪声正在影响我对图像的二进制阈值处理 为了忽略噪音 我尝试设置一个已知中心位置和半径的圆形蒙版 从而使该圆之外的所有像素都更改为黑
  • 公交车公共交通算法

    我正在开发一个可以查找公交路线的离线 C 应用程序 我可以提取时间表 巴士 路线数据 我正在寻找适用于基本数据的最简单的解决方案 可以使用什么算法来查找从巴士站 A 到巴士站 B 的路线 是否有适用于 C Java 的开源解决方案 数据库的
  • 自己绘制的WPF自定义滑块

    这是我关于堆栈溢出的第一个问题 所以不要踢它 我在尝试创建 Mac 风格的滑块控件时遇到问题 我已经发现这个解决方案 http www codeproject com KB miscctrl MAC Slider aspx我已经在我的解决方
  • 重载算术运算符

    赋值运算符可以声明为 T 运算符 const t 在类中 但不能以这种方式定义算术运算符 它必须是友元函数 我不明白为什么 你能解释一下吗 算术运算符不必须是友元 那么你可以这样定义 MyClass MyClass operator con
  • 更改私有模块片段是否会导致模块重新编译?

    On 此页面有关 C 20 模块功能 https www modernescpp com index php c 20 modules private module fragment and header units 我发现了这样的说法 借
  • main.cpp 是必需的吗?

    我试图编译一个程序cmake 我最终删除了我的main cpp文件 我刚刚将其复合到另一个包含我的项目名称的文件中 即 我刚刚将主函数剪切并粘贴到该文件中 问题是我有一个main cpp未发现错误 不确定是否在C 一个名为main cpp是
  • MINIX内部碎片2

    我正在用 C 语言编写一些软件 它递归地列出给定目录中的所有文件 现在我需要计算出内部碎片 我花了很长时间研究这个问题 发现 ext2 上的内部碎片只发生在最后一个块中 我知道理论上你应该能够从索引节点号获得第一个和最后一个块地址 但我不知
  • 将 AutomationID 与 ListView 结合使用

    我正在尝试将 AutomationId 附加到列表视图中的项目 理想情况下 将项目名称绑定到显示的项目
  • 运行实体框架自定义工具,它有什么作用?

    在 Visual Studio 中 当使用实体框架并为 tt 和 Context tt 文件应用运行自定义工具时 它是什么以及它有什么作用 为什么它解决数据库同步问题 有时 为什么我应该在运行 tt 之前运行它 Context tt 它被称
  • 具有多个父项的 Qt 树模型

    我想构建一棵树 其中一个元素可以引用另一个元素 我想要构建的树是 像这样的东西 A B C D E F P this is a pointer to C D first child of C E second child of C I fo
  • 查找数组中的多个索引

    假设我有一个像这样的数组 string fruits watermelon apple apple kiwi pear banana 是否有一个内置函数可以让我查询 apple 的所有索引 例如 fruits FindAllIndex ap
  • C++ 中的析构函数

    我的 AB h 文件中有一个构造函数 class AB private int i public AB i 0 constructor AB i 0 destructor virtual void methodA unsigned int
  • 如何配置 qt Creator 以显示 C++ 代码而不是反汇编程序?

    昨天我做了很多事情 比如更新 GCC Clang 和重新安装 Qt Creator 今天 在逐步调试我的代码时 调试器显示的是反汇编代码 而不是我编写的 C 代码 紧迫F10 or F11 调试器正在进入汇编代码而不是 cpp nor h我
  • 稀疏矩阵超定线性方程组c/c++库

    我需要一个库来解决 Ax b 系统 其中 A 是一个非对称稀疏矩阵 每行有 8 个条目 而且可能很大 我认为实现双共轭梯度的库应该没问题 但我找不到一个有效的库 我尝试过 iml 但 iml sparselib 包中缺少一些标头 有小费吗

随机推荐

  • H.265 3D视频编码

    实验方案 实验目的 对单视点视频 深度使用HEVC编码 编码使用不同量化步长 2 方案1 HTM 使用HTM 16 2 dev编码 选用3 view depth Nview depth qp seqContent 联合编码 注意修改3 vi
  • 《阿里大数据之路》读书笔记:第二章 日志采集

    第二章 日志采集 一 浏览器的页面日志采集 浏览器的页面型产品 服务的日志采集可分为两大类 页面浏览 展现 日志采集 指一个页面被浏览器加载呈现时采集的日志 此类日志是最基础的互联网日志 此类日志是目前所有互联网产品的两大基本指标 页面浏览
  • ssm框架中,mybatis的sql语句日志输出

    在ssm框架中 常用的日志输出为Log4j 但按照常规的配置 涉及mybatis那部分日志不能打印出来的 由于没有日志的输出 开发人员很难从控制台中迅速找出相应的sql语句 对调试和找错误带来了一定的困扰 针对这个问题 我们需要额外的配置以
  • AXI smartconnect

    AXI smartconnect 简介 AXI smartconnect 是为了一个或多个主机通过AXI总线和一个或多个从机进行数据读写而用的 此前常用的应该是AXI interconnect这个IP 实质上smartconnect是int
  • [无线]433M天线、2.4G天线、5G天线长度设计

    无线 无线传输距离预估计算 我们回顾一下 天线最佳长度为波长的1 4 波长 波速 频率 波速 光速 3 100000000 一段金属导线中的交变电流能够向空间发射交替变化的感应电场和感应磁场 这就是无线电信号的发射 相反 空间中交变的电磁场
  • 关于==和equals的深入了解

    关于 和equals的深入了解 比较的是地址 这里指的是对象的比较 如果是基本数据类型 则比较的是值 未被重写的equals比较也是地址 因为调用的是Object的equals方法 Object类中equals源码如下 public boo
  • angularjs2 ajax请求,AngularJS - 将ajax请求传递给另一个控制器

    我的页面中有两个表 当点击第一个表上的一行时 我想调用ajax请求来更新第二个表 我正在尝试使用两个控制器执行此操作 每个控制器都使用ng repeat填充带有值的行 我已经烧掉了我能买得起的每一个神经元 而且我仍然难过 这是我的代码 ap
  • 机器学习——逻辑回归

    一下理解均为本人的个人理解 如有错误 欢迎指出 文章目录 什么是逻辑回归 如何处理因变量取值离散的情况 如何求解w b 梯度下降法的推导 逻辑回归的用途 如何衡量逻辑回归模型的好坏 逻辑回归的使用条件 pytorch实现逻辑回归 什么是逻辑
  • React笔记(七) React路由

    React笔记 七 1 React路由理解 React实现的是SPA应用 即单页Web页面 整个应用中只有一个完整的页面 点击页面中的链接也不会刷新页面 只会对页面进行局部的刷新 因此在更换页面时需要使用路由实现 路由就是一个键值对映射关系
  • pip升级 以及python3升级python3.9

    Ubuntu16 04 升级pip问题 you are using pip version 8 1 1 however version 20 0 2 is available you should consider upgrading vi
  • python中的删除:remove()、pop()、del

    这三种方法都是list的删除方法 其中remove是针对可变列表的元素进行搜索删除 而pop和del是针对可变列表的下标进行搜索删除 具体区别如下 remove item 方法是直接对可变序中的元素进行检索删除 返回的是删除后的列表 不返回
  • 【AD20】关于AD设计过程中一些小细节

    线上实习学习AD的过程中 学习到的一些懒狗快捷技巧以及一些因版本问题的不同操作 就浅浅归纳了一下 目录 原理图相关 1 批量命名元件 2 阵列式粘贴 3 给元器件添加属性 PCB相关 1 自绘元件封装 2 自定义板子的形状 3 按板子形状铺
  • 树莓派摄像头监控&Android手机查看&浏览器查看

    树莓派摄像头监控 Android手机查看 浏览器查看 链接USB相关参考 源码 usb摄像机直接接入树莓派USB接口 1 安装motion pi raspberrypi code camera sudo apt get install mo
  • jpa limit查询_在JPA的@Query注解中使用limit条件(详解)

    在 Query注解注释的JPQL语句中写limit语句是会报错的 unexpected token limit near line 解决方法是讲 Query注解中的limit语句去掉 然后传一个Pageable pageable new P
  • 6个网页背景特效源码 canvas+three.js科技贴图 webgl源码

    隧道穿梭特效 粒子矩阵特效 几何随机变换特效
  • websocket传输速率_STM32 websocket,TCP和UDP的传输速率

    网络上经常有人提到websocket TCP和UDP 的差别 说的大都是协议之间的差别 没有提及它们的传输能力 为了设计高吞吐量的物联网微服务器 最近对websocket TCP UDP的传输能力做了测试 使用STM32F746 处理器 操
  • unity打开除主菜单其他地方黑屏或白屏与unityHub安装unity简介

    unity打开除主菜单其他地方黑屏或白屏 新安装完成unity后 解决与原因 缘由 新安装完成unity后 打开unity进入项目后 只显示出主菜单栏 其他为白屏或黑屏 如下图 解决与原因 具体原因没仔细去查百度了一下 可以是时区的设置问题
  • MatLab中滤波器(filterDesigner)的设计和使用(附代码)

    本文章只作为本人学习笔记使用 matlab具有非常使用的滤波器设计工具 关于如何找到这个小工具有两种方法 1 我们可以在命令行输入filterDesigner 不同版本命令可能会有所不同 2 在APP页面中找到filterDesigner
  • 控制研究的混杂因素(Confounder)

    高高兴兴地写完一篇 SCI 投稿 苦苦等待好久 却只等来审稿人的一句话 你有控制研究的混杂因素 Confounder 吗 额 什么是混杂因素 又该如何控制 其实 混杂因素的控制在研究设计阶段就应该注意 今天 笔者就从 什么是混杂因素 为什么
  • C++学习:动态内存

    动态内存 静态内存用来保存局部static对象 类static数据成员 定义在任何函数之外的变量 static对象在使用之前分配 在程序结束后销毁 栈内存用来保存定义在函数内的非static对象 对于栈对象 仅在其定义的程序块运行时才存在