C++学习笔记----6、内存管理(一)---- 使用动态内存(2)

news2024/11/15 1:33:38

2.2、我的好朋友malloc怎么样了?

       如果你是一个C程序员,对啦,我就是,你可能会想,malloc()函数怎么样了。在C语言中,malloc()用于分配一定数量的内存字节。总的来讲,使用malloc()简单直接。在C++中malloc()函数依然存在,但你要尽量避免使用它。New比malloc()有优势的地方就是new不仅仅分配内存,它还构造对象。

       例如,考虑以下两行代码,使用了一个叫做Foo的假想类:

Foo* myFoo { (Foo*)malloc(sizeof(Foo)) };
Foo* myOtherFoo { new Foo{} };

        执行完这些代码后,myFoo与myOtherFoo指向了能够放置Foo对象的自由内存空间。使用这两个指针都能访问到Foo的成员变量与成员函数。不同的地方在于被 myFoo指向的Foo对象不是一个合适的对象,因为它的构造函数没有被调用到。Malloc()函数只是设定了一定数量的内存。它不知道也不关心对象。而恰恰相反,对new的调用分配了合适的内存并且调用了合适的构造函数来构造这个对象。

       同样的不同也存在于free()函数与delete操作符之间。对于free(),对象的析构函数没有被调用。而对于delete,析构函数被调用且对象被合适地清理。

       在C++中要避免使用malloc()与free()。

2.3、当内存分配失败

        如果不是全部的话,也是大部分程序员在写代码的时候,问题假设New总是成功的。道理是如果new失败的话,就意味着内存很低,生命非常非常糟糕。也经常是一种难以理解的状态吧,因为不知道你的程序怎么样了,在这种情况下还能做什么呢?

       缺省情况下,当new失败时要抛出异常,例如,对于申请的内存不够。如果异常没有被捕获,程序就会中止。在许多程序中,这种行为是可以被接受的。我们以后还会详细讲解异常,提供从内存不足的情况下优雅恢复的可能的方法。

       还有一种版本的new,它不抛出异常。当内存分配失败时它返回一个nullptr,与C中malloc()的行为类似。使用这种版本的new的语法如下:

int* ptr { new(nothrow) int };

       这种语法有一点奇怪:你把nothrow当做new的参数来用,实际上还就是。

       当然了,与抛出异常的版本一样,你仍然会有同样的问题—当结果是nullptr时怎么做?编译器并不要求你去检测这个结果,所以nothrow版本的new比抛出异常的版本的更可能带来其他的问题。基于这个原因,建议使用标准版本的new。如果从内存不足中恢复对你的程序非常重要,我们以后讨论的技巧会给你需要的工具。

3、数组

       数组就是同类型的多个变量放到一个带有索引的单个变量中。使用数组对于初级程序员来说是很自然的,因为对于以数字标识的值来说很容易理解。内存内的数组也是这种思想模型。

3.1、原型数组

       当你的程序为一个数组分配内存时,它分配了一块连续的内存片,每一小块可以放置数组的一个元素。例如,一个本地的int数组可以在栈上声明如下:

int myArray[5];

        每个原型数组中的元素都没有初始化;也就是说,在内存中可以是任何值。下图显示了数组生成时的内存状态。当在栈上生成数组时,在编译时一定要知道其值的大小。

       有些编译器允许在栈上有变长数组。这不是C++的标准属性,所以建议使用时要仔细。

       当在栈上生成一个数组时,可以用一个初始化列表来提供初始值:

int myArray[5] { 1, 2, 3, 4, 5 };

        如果初始化列表中包含的元素比数组的少,余下的元素都为0,例如:

int myArray[5] { 1, 2 }; // 1, 2, 0, 0, 0

        把所有元素都初始化为0,简单如下:

int myArray[5] { }; // 0, 0, 0, 0, 0

        当使用初始化列表时,编译器可以自动推断出元素的数量,就不需要显示地给出数组的大小了:

int myArray[] { 1, 2, 3, 4, 5 };

        在自由内存空间上声明数组也一样,除了使用指针指向数组的位置之外。以下代码为5个未初始化的int分配了内存,保存了一个指向叫做myArrayPtr的变量的指针:

int* myArrayPtr { new int[5] };

        下图展示了与栈上数组类似的自由内存空间数组,只是位置不同而已。myArrayPtr变量指向数组的第0个元素。

        与new操作符一样,new[]接受nothrow变量返回nullptr,而不是抛出异常,当分配失败时:

int* myArrayPtr { new(nothrow) int[5] };

        在自由内存空间上动态创建的数组也可以用初始化列表来初始化:

int* myArrayPtr { new int[] { 1, 2, 3, 4, 5 } };

        对new[]的每一次调用都应该对应地去调用delete[]来清理内存。注意在delete[]后面的空的花括号!

delete [] myArrayPtr;
myArrayPtr = nullptr;

        把数组放到自由内存空间的优势是可以在运行时定义大小。例如,以下代码片断接收了从一个假想叫做askUserForNumberOfDocuments()的函数的一定数量的文件,使用这个结果生成Document对象的数组。

Document* createDocumentArray()
{
    size_t numberOfDocuments { askUserForNumberOfDocuments() };
    Document* documents { new Document[numberOfDocuments] };
    return documents;
}

        记住对每一个new[]的调用都应该对应地调用delete[],所以在这个例子中,createDocumentArray()的调用者很重要的一点就是要使用delete[]来清理返回的内存。另一个问题就是C风格的数组是不知道它们的大小的;这样的话,createDocumentArray()的调用者也不知道返回数组中到底有多少元素!

       在以前的函数中,documents是一个动态分配的数组。不要将其与动态数组相混淆。数组本身并不是动态的,因为一旦分配了其大小就不会发生改变。动态内存让你给出运行时的分配空间的大小,但是它不会自动调整大小来放置数据。

       数据结构确实在动态调整其大小,也确实知道其真实的大小,例如,标准库构造函数。应该使用这样的构造函数,而不应该使用C风格的数组,因为它们在使用上更安全。

       在C++中有一个函数叫做realloc(),是从C语言中继承来的。别用它,在C中,realloc()用于通过分配新的内存空间来有效改变数组的大小,把旧的数据拷贝到新的位置,删除原来的内存块。在C++中这个方法是非常危险的,因为用户定义的对象对于位字节拷贝不灵光。

       永远不要在C++中使用realloc()!它已不再是你的朋友。

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

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

相关文章

传统CV算法——图像特征算法之角点检测算法

文章目录 2. 角点检测2.1 角点概述2.1.1 概念2.1.2 角点的特点2.1.3 角点的检测2.1.4 角点的应用 2.2 角点检测算法2.2.1 Harris 角点2.2.1.1 Harris 角点介绍2.2.1.2 Harris计算流程1. 图像梯度2. 结构张量3. Harris响应函数4. 非极大值抑制5. 阈值化 2.2.1.3 Harris性质1. 旋…

《PCI Express体系结构导读》随记 —— 第II篇 第7章 PCIe总线的数据链路层与物理层(4)

接前一篇文章:《PCI Express体系结构导读》随记 —— 第II篇 第7章 PCIe总线的数据链路层与物理层(3) 7.1 数据链路层的组成结构 7.1.1 数据链路层的状态 数据链路层需要通过物理层监控PCIe链路的状态,并维护数据链路层的“控制与…

厂房电气火灾现场勘验要点

0前言 随着我国社会的发展,电气化水平提升,但随之而来的是频繁的电气火灾事故,对生活和生产造成重大危害。电气火灾是最常见的火灾类型,通常由电路短路、电压过高、电阻过大或电路超负荷引起,这些因素都可能导致火花并…

电脑怎么录屏?探索电脑录屏工具,三款高效工具推荐及使用指南

在数字化时代,电脑录屏已成为日常工作和学习中不可或缺的一部分。无论是制作教程、记录会议还是捕捉游戏精彩瞬间,一个好的录屏工具都能让这一切变得简单高效。今天,我们将为您介绍三款备受推崇的录屏软件:Windows自带的步骤记录器…

面向对象程序设计之链表 list 的简析(C++)

简介:链表是一个双向的结构,与string与vector不同的是他不支持[]访问,因为链表是由一个节点一个节点连接而成的,并不连续。我们可以在常数量级内对于链表进行插入与删除数据 1.构造函数 我们在cplusplus.com中可以查到链表总共有四…

无人机遥控器的材料组成!!!

1. 外壳 材料:遥控器外壳通常采用高强度塑料(如ABS、PC等)或轻质金属(如铝合金)制成。这些材料具有良好的抗冲击性、耐磨性和一定的耐腐蚀性,能够保护内部电子元件免受外界环境的影响。 特点:…

智能优化算法-秃鹰优化算法(BES)(附源码)

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1.内容介绍: 秃鹰搜索算法‌,它是一种基于自然界中秃鹰觅食行为启发的优化算法,旨在解决优化问题。该算法模仿了秃鹰在寻找猎物时的策略,结合了随机搜索和逐步优化的特点&#…

AGI系列(9)手把手带你玩转 Coze 画板节点

本文以智能体“日签卡片生成器”的制作来阐述 Coze 画板节点的使用方法。 效果演示 核心流程 日签卡片生成器工作流整体分为两部分: 工作流:其核心流程为通过用户输入的主题词生成卡片的标题、内容 图像流:通过LLM输出的内容在图像流完成卡…

【C++ Primer Plus习题】9.3

问题: 解答: #include <iostream> using namespace std;struct chaff {char dross[20];int slag; };int set_chaff(chaff& f, char* c, int n) {if (strlen(c) > 0){strcpy_s(f.dross, c);f.slag n;return 1;}return 0;}void show_cahff(const chaff& f) {c…

rabbitmq高可用集群搭建

需求分析基本情况 在进行RabbitMQ搭建时&#xff0c;我们基于现有的连接数据和业务需求进行了深入分析。目前的统计数据显示&#xff0c;连接数为631&#xff0c;队列数为80418。为了确保业务需求的顺利满足&#xff0c;我们需要在云产品和自建RabbitMQ消息队列服务之间做出选…

最新软件测试面试题,常见面试题及答案汇总,不怕拿不到offer

面试题包括以下十六个模块&#xff1a;软件测试基础&#xff0c;liunx基础&#xff0c;MySQL基础&#xff0c;web测试&#xff0c;APP测试&#xff0c;性能测试&#xff0c;selenium&#xff0c;Python基础&#xff0c;接口测试&#xff0c;lordrunner&#xff0c;计算机网络&a…

chapter11-枚举和注解——(注解)——day14

目录 433-override注解 434-Deprecated注解 435-SupressWarnings注解 436-JDK的元注解 433-override注解 434-Deprecated注解 435-SupressWarnings注解 436-JDK的元注解

华为云征文 | 华为云Flexus云服务器X实例之Docker环境下部署JmalCloud个人网盘

华为云征文 | 华为云Flexus云服务器X实例之Docker环境下部署JmalCloud个人网盘 前言一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 Flexus云服务器X实例特点1.3 Flexus云服务器X实例使用场景 二、JmalCloud介绍2.1 JmalCloud简介2.2 JmalCloud优点2.3 JmalCloud使…

Android Camera系列(一):SurfaceView+Camera

心行慈善&#xff0c;何需努力看经—《西游记》 本系列主要讲述Android开发中Camera的相关操作、预览方式、视频录制等&#xff0c;项目结构代码耦合性低&#xff0c;旨在帮助大家能从中有所收获&#xff08;方便copy :&#xff09; &#xff09;&#xff0c;对于个人来说也是一…

【Next】2. 项目构建

打开 Next.js 的官方文档&#xff1a;https://nextjs.org/docs/getting-started/installation&#xff08;国内文档不够新&#xff09; Next.js 版本 14.2 &#xff0c; Node.js 的版本要求必须 > 18.18。 Next 有两种开发模式&#xff0c;下面讲新的 APP Router。 创建项…

VS2022 C++ 控制台中文乱码解决方案

最近写读文件的代码时&#xff0c;遇到了VS控制台读取中文时出现乱码&#xff0c;看了网上主要有两种方法 &#xff1a; 1、在VS菜单栏里点击"文件"选项&#xff0c;然后选择"高级保存选项"来设置文件格式&#xff0c;但是我的文件选项里没有"高级保存…

COT报告:美国期货市场持仓情况分析

市场情绪的晴雨表 COT报告揭示了美国期货市场中不同参与者的持仓情况&#xff0c;尤其是净多头和净空头头寸。这份报告发布时会有约三天的滞后&#xff0c;因此提供的是过往数据。通常&#xff0c;该报告在星期五发布&#xff0c;反映的是截至前一星期二的数据&#xff0c;因此…

蓝牙地址BD Addr烧录

关于蓝牙地址,有很多文章有介绍,主要要知道下面一个图: 蓝牙设备地址(或BD_ADDR)是制造商分配给每个蓝牙设备的唯一48位标识符。蓝牙地址通常显示为以十六进制书写的6个字节,用冒号分隔(例如-00:11:22:FF:EE)。蓝牙地址的上半部分(最重要的24位)被称为组织唯一标识符…

MASM32+ HTML JavaScript,好搭档

哪个编程工具让你的工作效率翻倍&#xff1f; 在日益繁忙的工作环境中&#xff0c;选择合适的编程工具已成为提升开发者工作效率的关键。不同的工具能够帮助我们简化代码编写、自动化任务、提升调试速度&#xff0c;甚至让团队协作更加顺畅。那么&#xff0c;哪款编程工具让你…

「Python数据分析」Pandas进阶,使用merge()函数合并数据

在使用python语言进行数据分析的过程中&#xff0c;我们的数据&#xff0c;有很大一部分是结构化数据&#xff0c;也就是比较整齐的数据。 这里&#xff0c;我不展开讲什么是结构化数据&#xff0c;因为这个范围太过于庞大。但是&#xff0c;有一个知识点&#xff0c;必须要讲…