C++ Primer 第五版 第12章 动态内存

C++Primer第五版 习题答案 目录 C++Primer第五版 习题答案 本文当作我学习C++的一个记录,这里的习题答案并不是标准答案,仅仅是我的理解,如有错误,请大家指出,谢谢! 我参考的文章会在文末列出,谢谢大家。 第一章 ... 阅读详情

动态分配的对象的生存期与它们在哪里创建的是无关的,只有当显式地被释放时,这些对象才会销毁。

为了更安全地使用动态对象,标准库定义了两个智能指针类型来管理动态内存分配的对象。当一个对象应该被释放时,指向它的智能指针可以确保自动地释放它。

静态内存用来保存局部static对象,类static数据成员以及定义在任何函数之外的变量。

栈内存用来保存定义在函数内的非static对象。

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

除了静态内存和栈内存,每个程序还拥有一个内存池。这部分内存被称为自由空间(free store)或堆(heap)。程序用堆来存储动态分配(dynamically allocate)的对象——即,那些在程序运行时分配的对象。

一、动态内存与智能指针

在C++中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象进行初始化;delete,接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。

标准库提供了两种智能指针(smart pointer)类型来管理动态对象。这两种智能指针的区别在于管理底层指针的方式:shared_ptr允许多个指针指向同一个对象;unique_ptr则“独占”所指向的对象。标准库还定义了一个名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象。这三种类型都定义在memory头文件中。

智能指针是模板。当我们创建一个智能指针时,必须提供额外的信息——指针可以指向的类型。和vector一样,我们在尖括号内给出类型,之后是所定义的这种智能指针的名字。默认初始化的智能指针中保存着一个空指针。

1. shared_ptr类

make_shared函数

最安全的分配和使用动态内存的方法是调用一个名为make_shared的标准库函数。此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。与智能指针一样,make_shared也定义在头文件memory中。

make_shared用其参数来构造给定类型的对象。传递的参数必须与该类型的某个构造函数相匹配。如果我们不传递任何参数,对象就会进行值初始化。

通常用auto定义一个对象来保存make_shared的结果。

shared_ptr的拷贝和赋值

当进行拷贝或赋值操作时,每个shared_ptr都会记录有多少个其他shared_ptr指向相同的对象。我们可以认为每个shared_ptr都有一个关联的计数器,通常称其为引用计数(reference count)。一旦一个shared_ptr的计数器变为0,它就会自动释放自己所管理的的对象。

当指向一个对象的最后一个shared_ptr被销毁时,shared_ptr类会自动销毁此对象。它是通过另一个特殊的成员函数——析构函数(destructor)完成销毁工作的。每个类都有一个析构函数,用于控制次类型的对象销毁时做什么操作。析构函数一般用来释放对象所分配的资源。

定义StrBlob类

定义一个名为StrBlob的类,保存一组元素。与容器不同,我们希望StrBlob对象的不同拷贝之间共享相同的元素。即,当我们拷贝一个StrBlob时,原StrBlob对象及其拷贝应该引用相同的底层元素。

我们使用vector来保存元素。将vector保存在动态内存中,为每个StrBlob设置一个shared_ptr来管理动态分配的vector。此shared_ptr的成员将记录有多少个StrBlob共享相同的vector,并在vector的最后一个使用者销毁时释放vector。

StrBlob构造函数

元素访问成员函数

访问元素之前必须检查元素是否存在。check函数检查一个给定索引是否在合法范围内。除了索引,check还接受一个string参数,它会将此参数传递给异常处理程序,这个string描述了错误内容。

2. 直接管理内存

C++语言定义了两个运算符来分配和释放动态内存。运算符new分配内存,delete释放new分配的内存。

自己直接管理内存的类与使用智能指针的类不同,它们不能依赖于类对象拷贝、赋值和销毁操作的任何默认定义。

使用new动态分配和初始化对象

在自由空间分配的内存是无名的,因此new无法为其分配的对象命名,而是返回一个指向该对象的指针:

此new表达式在自由空间构造一个int型对象,并返回指向该对象的指针。

默认情况下,动态分配的对象是默认初始化的,这意味着内置类型或组合类型的对象的值将是未定义的,而类类型对象将用默认构造函数进行初始化:

我们可以使用直接初始化方式来初始化一个动态分配的对象。

也可以对动态分配的对象进行值初始化,只需在类型名之后跟一对空括号即可:

只有当括号中仅有单一初始化器时才可以使用auto:

动态分配的const对象

用new分配const对象是合法的:

内存耗尽

一旦一个程序用光了它所有可用的内存,new表达式就会失败。默认情况下,如果new不能分配所要求的内存空间,它会抛出一个类型为bad_alloc的异常。我们可以改变使用new的方式来阻止它抛出异常:

我们称这种形式的new为定位new(placement new)。定位new表达式允许我们向new传递额外的参数。在此例中,我们传递给它一个由标准库定义的名为nothrow的对象。如果nothrow传递给new,我们的意图是告诉它不能抛出异常。bad_alloc和nothrow都定义在头文件new中。

释放动态内存

delete表达式执行两个动作:销毁给定的指针所指向的对象;释放对应的内存。

释放一块非new分配的内存,或者将相同的指针值释放多次,其行为是未定义的。

由内置指针(而不是智能指针)管理的动态内存在被显式释放前一直都会存在。

与类类型不同,内置类型的对象被销毁时什么也不会发生。

delete之后重置指针值

当我们delete一个指针后,指针变成空悬指针(dangling pointer),即,指向一块曾经保存数据对象但现在已经无效的内存的指针。

为了避免空悬指针:在指针即将要离开其作用域之前释放掉它所关联的内存。如果我们需要保留指针,可以在delete之后将nullptr赋予指针,这样就清楚地指出指针不指向任何对象。

3. shared_ptr和new结合使用

如果我们不初始化一个智能指针,它就会被初始化为一个空指针。我们可以用new返回的指针来初始化智能指针。

接受指针参数的智能指针构造函数是explicit的。因此,我们不能将一个内置指针隐式转换为一个智能指针,必须使用直接初始化形式来初始化一个智能指针。

不要混合使用普通指针和智能指针,也不要使用get初始化另一个智能指针或为智能指针赋值。

智能指针类型定义了一个名为get的函数,它返回一个内置指针,指向智能指针管理的对象。此函数是为了这样一种情况而设计的:我们需要向不能使用智能指针的代码传递一个内置指针。使用get返回的指针的代码不能delete此指针。

4. 智能指针和异常

5. unique_ptr

与shared_ptr不同,某个时刻只能有一个unique_ptr指向一个给定对象。当unique_ptr被销毁时,它所指向的对象也被销毁。

当我们定义一个unique_ptr时,需要将其绑定到一个new返回的指针上。类似shared_ptr,初始化unique_ptr必须采用直接初始化形式:

unique_ptr不支持普通的拷贝或赋值操作。

6. weak_ptr

weak_ptr是一种不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。

当我们创建一个weak_ptr时,要用一个shared_ptr来初始化它。

由于对象可能不存在,我们不能使用weak_ptr直接访问对象,而必须调用lock。

二、动态数组

C++语言定义了另一种new表达式语法,可以分配并初始化一个对象数组。标准库中包含一个名为allocator的类,允许我们将分配和初始化分离。使用allocator通常会提供更好的性能和更灵活的内存管理能力。

1. new和数组

为了让new分配一个对象数组,我们在类型名之后跟一对方括号,在其中指明要分配的对象的数目。

也可以用一个表示数组类型的类型别名来分配一个数组。

分配一个数组会得到一个元素类型的指针

动态数组不是数组类型,因此不能对动态数组调用begin或end,也不能用范围for语句来处理(所谓的)动态数组中的元素。

初始化动态分配对象的数组

动态分配一个空数组是合法的

释放动态数组

为了释放动态数组,我们使用一种特殊形式的delete——在指针前加上一个方括号对。

数组中的元素按逆序销毁,即最后一个元素首先被销毁,然后是倒数第二个,依此类推。

智能指针和动态数组

标准库提供了一个可以管理new分配的数组的unique_ptr版本。为了用一个unique_ptr管理动态数组,我们必须在对象类型后面跟一对空方括号:

当一个unique_ptr指向一个数组时,我们不能使用点和箭头成员运算符,但可以使用下标运算符来访问数组中的元素。

2. allocator类

标准库allocator类定义在头文件memory中,它帮助我们将内存分配和对象构造分离开来。它提供一种类型感知的内存分配方法,它分配的内存时原始的、未构造的。我们需要在此内存中构造对象。

allocator是一个模板。为了定义一个allocator对象,我们必须说明这个allocator可以分配的对象类型。当一个allocator对象分配内存时,它会根据给定的对象类型来确定恰当的内存大小和对其位置:

拷贝和填充未初始化内存的算法

标准库为allocator类定义了两个伴随算法,可以在未初始化内存中创建对象。它们定义在头文件memory中。这些函数返回(递增后的)目的位置迭代器。

C++ Primer Plus(第六版)编程练习答案 所有章节汇总 本博客汇总了本人历时一年学完《C++ Primer Plus (第6版)》所做的所有编程练习的答案,供大家学习参考和交流。 以下附上各章节的答案详解博客地址,以及源码工程下载地址。 PS:源码下载大部分都是需要积分的,当时设置的时候好像有点乱,有的是1积分,有的是3积分,最难的第12章和第13章我设置的是不要积分,大家都可以下载下来自己运行一下看看结果。 第 2 章 开始学习C++: ... 阅读详情

相关推荐

C++ Primer Plus(第六版)编程练习答案 第12章 类和动态内存分配

本章所有编程练习的工程源码可在此处下载(点击此链接下载),供大家参考交流!   1. 对于下面的类声明: class Cow {          char name[20];          char *hobby;          double weight; public:          Cow();          Cow(const char * nm, co...

清水河C罗——Leonardo-Liu 4676

C++primer(第五版)第十二章(动态内存)

C++中内存包含静态内存,栈内存,自由空间(堆).静态内存用于保存局部的static(静态)对象,以及定义于任何函数以外的变量(全局变量).栈内存用来保存定义在函数内的非static对象,由编译器自动创建和销毁.程序可以用堆来存储动态分配的对象,同时也需要由我们来显式地销毁.

m0_63235356的博客 208

海外支付实战:虚拟信用卡订阅ChatGPT Plus等服务的完整指南

在跨境数字服务消费中,支付环节常因地区限制、银行风控等因素受阻。其核心原理在于国际信用卡交易需通过发卡行风控系统,而国内银行对高频、小额或商户名非常规的境外线上交易敏感,导致成功率不稳定。为解决这一痛点,虚拟信用卡技术应运而生,它通过服务商生成关联预充值账户的虚拟卡号,提供地域灵活性与资金可控性,显著提升了支付通过率。这项技术的价值在于以较低学习成本,为个人用户打通了访问ChatGPT Plus、Midjourney、Claude Pro等前沿AI服务的支付通道。其典型应用场景包括订阅各类海外SaaS、内容

weixin_42531579的博客 1032

《C++ Primer》导学系列:第 12 章 - 动态内存

本节总结了解了动态内存分配与释放的基本概念和操作,掌握了new和delete的使用方法。理解了智能指针的基本概念,掌握了和的使用方法。通过智能指针的使用,能够有效避免内存泄漏和双重释放问题,提高了程序的可靠性和稳定性。提高建议多练习智能指针的使用:通过编写更多涉及智能指针的程序,熟悉各种智能指针的用法,提高对动态内存管理的能力。深入理解智能指针的原理:通过阅读文档和相关书籍,深入理解智能指针的实现原理和使用场景,提高编写高效代码的能力。避免常见内存管理错误。

iShare_Carlos的博客 1392

Qt —— 调用海康C++版SDK获取摄像头每帧图像,通过OpenCv处理每帧图像后显示在Qt窗口(附:源码)

  关注 笔者 - jxd 微信公众号搜索 “码农总动员” 或 微信扫描下方二维码,了解更多你不知道的XX,O(∩_∩)O

5447

SRS流媒体服务器在Windows下的安装

在之前的流媒体开发中(视频会议),我基本上使用nginx加模块的方式进行学习、测试,正式开发的时候改为服务器端用EasyDarwin,客户端用rtsp-simple-server(这些流媒体服务器的用法见我以前的博文),这样可以充分利用客户端的资源,降低服务器端的压力。在流媒体协议方案,我选择相对较快的rtsp。这个协议优点是支持UDP协议,优化好的环境下可以实现3秒以下的延迟,基本满足甲方要求,缺点就是不支持网页播放。

dgnankai的专栏 2023

C++ Primer学习笔记-----第十二章:动态内存

new在动态内存中为对象分配空间并返回一个指向该对象的指针,可以对对象进行初始化。静态内存保存局部static对象、类static数据成员、定义在任何函数之外的变量。为了更容易更安全地使用动态内存,新的标准提供了两种只能指针类型来管理动态对象。delete接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。只能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。C++Primer学习笔记-----第十二章动态内存。栈内存保存定义在函数内的非static对象。......

weixin_41155760的博客 585

OGRE 3D----2. QGRE + QQuickView

将 OGRE(面向对象图形渲染引擎)集成到使用 QQuickView 的 Qt Quick 应用程序中,可以在现代灵活的 UI 框架中提供强大的 3D 渲染功能。本文将指导您如何在 QQuickView 环境中设置 OGRE。

charce_you的专栏 915

C++_Primer_学习笔记_第十二章(动态内存)

第十二章(动态内存) 1).动态分配对象的生存期和它们在哪里创建是没有关系的,只有显式地被释放时,这些对象才会被释放。 2).为了解决动态对象能够被正确释放的问题,设置了智能指针。当一个对象应该被释放时,指向它的智能指针可以确保自动地释放它。 3).静态内存。 局部static变量。 类的static数据成员 全局变量 4).栈内存。保存局部变量。 5).静态内存和栈内存,由编译器自动创建和销毁。 6).程序的自由空间,或者堆。程序可以用堆,存储动态分配(程序运行时分配)的对象(它的创建和销毁由程序代码

YRC的博客 453

给跨代引用记一本账:Java GC 的分配路径、卡表写屏障与收集器版图快速回顾

本文把 Java GC 的零散名词串成一条推理链路:从 TLAB 指针碰撞分配、逃逸分析,到 Eden、Survivor 与晋升的四条路,重点拆解卡表与写屏障如何为老年代指向新生代的引用记账,及 Minor GC 如何只扫脏卡。基于 JDK 8 实测:分散写使 Young GC 停顿涨 10~15 倍,条件卡标记消除卡表伪共享,计数循环让 System.gc 等待 2.7 秒,Survivor 过小使晋升量增加约 400 倍。文末梳理 JDK 8 到 27 的收集器演进、选型路径与排查顺序。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 17万+

手把手教你玩转服务器芯片架构​专栏--​​3.5 实战案例:用SystemC搭建一个多核服务器芯片的NoC模型(含流量分配与延迟仿真)​

通过SystemC搭建多核NoC模型,可深入验证流量分配策略与延迟特性。实际工程中需结合FPGA原型验证(如Xilinx Alveo)进行时序收敛分析,并通过参数化设计适配不同服务器芯片需求。

MHD0815的博客 3048

C++ primer 第12章:动态内存。个人学习笔记。

c++ primer 第12章 动态内存 个人学习笔记

weixin_45154969的博客 406

工业级向量检索核心技术:IVF-PQ原理与全流程解析

在大规模高维向量检索场景中,IVF-PQ(倒排索引结合乘积量化)凭借“粗筛范围+细算距离”的双重加速策略,成为核心解决方案。本文将深入解析其原理与全流程,助力开发者掌握这一关键技术。

进一步有进一步的欢喜~ 1199

《C++ Primer中文版(第五版)》 第12章 动态内存

动态分配的对象的声明周期与它们在哪里创建是无关的,只有当显式地被释放时,这些对象才会销毁。

LanGui_3000博客 284

YOLOv8改进 | 融合篇,YOLOv8主干改进融合网络之MobileNetV3+CA注意机制,助力涨点

MobileNetV3通过结合硬件感知网络架构搜索(NAS)和NetAdapt算法,通过新颖的架构改进进一步提升了性能。YOLOv8中的主干网络替换成MobileNetV3+引入CA注意机制

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 1884

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

C++ Primer 第五版 学习总结(十二) 第12章 动态内存

程序用堆(heap)来存储动态分配(dynamically allocate)的对象。动态对象的生存期由程序控制。

cf18862344377的博客 377

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C++ Primer 第5版——shared_ptr和StrBlob类

《C++ Primer》第五版,第12章,主要是介绍了动态内存与智能指针方面的知识点。 C++ 11新标准,提供了两种智能指针类型shared_ptr和unique_ptr来管理动态内存。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。 我们平时创建动态内存及释放内存的方式,例如: int *pt = new int(11); delete pt; 使用智能指针的方...

酒红的专栏 864

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

重新学习《C++Primer5》第12章-动态内存

12.1动态内存与智能指针12.1.1 shared_ptr类1.智能指针也是模板,定义方式一样 2.make_shared<>最安全的分配和调用方法auto p=make_shared<vector<string>>();//指向一个动态分配的空vector 3.引用计数auto r=make_shared<int>(42); r=q;//递增q指向的对象的引用计数;递减r指向的引用计数

yanglusheng的专栏 1292

《c++ primer》第五版 第十二章 动态内存

全局对象在程序启动时分配,在程序结束时销毁。 局部对象,当我们进入其所在的程序块时被创建,在离开块时被销毁。 局部static对象,在第一次使用前分配,在程序结束时销毁。 动态分配对象时,它的生存期与他们在哪里创建是无关的,只有当显式的被释放时,这些对象才能被销毁。 为了更安全使用动态对象,标准库定义了两个智能指针类型来管理动态分配的对象,当一个对象应该被释放的时候,指向他的智能指针可以确

还在路上的蒲公英 582

C++ primer学习笔记 第十二章 动态内存

对象的生命周期: 全局对象在程序启动时分配,结束时销毁。 局部对象在进入程序块时创建,离开块时销毁。 局部static对象在第一次使用前分配,在程序结束时销毁。 动态分配对象:只能显式地被释放。 对象的内存位置: 静态内存用来保存局部static对象、类static对象、定义在任何函数之外的变量。 栈内存用来保存定义在函数内的非static对象。 堆内存,...

Vermont_的博客 333

C++基础 - 智能指针 weak_ptr 用途之核查指针类

weak_ptr 是一种不控制所指向对象生存期的智能指针,它指向有一个 shared_ptr 管理的对象。将一个 weak_ptr 绑定到 shared_ptr 不会改变 shared_ptr 的引用计数。一旦最后一个指向对象的shared_ptr 被销毁,对象就会被释放。即使有 weak_ptr 指向对象,对象也还是会被释放。 因此不能直接用 weak_ptr 访问对象,而必须调用 lock 检查其指向的对象是否仍存在。如果存在,lock 返回一个指向共享对象的 shared_ptr。因此,只要此 s.

一只羊 318

青龙面板 + QLScriptPublic 指南:如何 5 分钟部署一套 100+ 的自动化签到脚本

早上九点的电梯里、通勤地铁上、午休的工位前——你大概也有过这样的时刻:手机里躺着一二十个 App 和小程序,每个都藏着"每日签到""积分任务""浏览赚金币",手动点一遍少说十几分钟,隔天再点又是一遍,漏一天还断了连续签到。QLScriptPublic 配合青龙面板做的,就是把这类重复劳动交给脚本定时执行:你只负责把账号信息填一次,剩下的交给 cron。这个仓库目前收拢了 100 多个可用脚本,覆盖

gitblog_00937的博客 915

c++ primer plus学习笔记_第12章 类和动态内存分配

c++ primer plus>第六版。

编程驴子的博客 2452

【c++ primer 笔记】第12章 动态内存

🎉作者简介:👓博主在读机器人研究生,目前研一。对计算机后端感兴趣,喜欢c++,go,python,目前熟悉c++,go语言,数据库,网络编程,了解分布式等相关内容📃个人主页:🔎支持👍就是给予我最大的支持!🎁💛本文摘要💛。

小呆鸟blog 643

MCP SEP-2484 解读:以一致性测试(Conformance Tests)作为规范提案进入 Final 状态的硬性门槛

本文以 Model Context Protocol 规范仓库中的 [SEP-2484](https://link.gitcode.com/i/9973df74940664d1fbfee90a0a357365) 为骨架,系统讲解 MCP 社区如何通过"一致性测试 + 可追溯性文件(traceability file)"机制,把规范的英文散文与 SDK 的可执行实现对齐。读完本文,你将掌握:哪些 S

gitblog_01000的博客 1072

Node-RED 数据处理实战手册:JSON、XML、CSV 的互转与排错

Node-RED 的数据处理,主要靠核心解析器里的一组节点完成:JSON、XML、CSV(还有 HTML、YAML),它们能把 msg 里的字符串、对象和表格数据互相转换。这篇文章不按"技巧清单"罗列,而是跟着一条数据在流程里走完全程:怎么从字符串变成对象,怎么在 XML 和 CSV 之间互转,字段对不上或坏消息出现时怎么办,最后再看怎么提速。 ## 数据入口:三步把 JSON 字符串解析成对象

gitblog_00964的博客 1058
上一篇: CUDA C 编程权威指南 第一章 基于CUDA的异构并行计算
下一篇: C++ Primer 第五版 第十三章 拷贝控制
青禾子的夏
博客等级 码龄8年 405粉丝 68原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值