C++中低级内存操作

C++中低级内存操作

C++相较于C有一个巨大的优势,那就是你不需要过多地担心内存管理。如果你使用面向对象的编程方式,你只需要确保每个独立的类都能妥善地管理自己的内存。通过构造和析构,编译器会帮助你管理内存,告诉你什么时候需要进行内存操作。将内存管理隐藏在类中显著提高了可用性,这一点在标准库类中得到了很好的体现。

然而,在某些应用程序或遗留代码中,你可能会遇到需要更低级别地操作内存的情况。无论是出于遗留代码、效率、调试还是好奇心,了解如何操作原始字节总是有帮助的。

指针

C++编译器会使用指针的声明类型来允许你进行指针算术。如果你声明了一个指向整数的指针并将其增加1,那么这个指针在内存中前进的距离是整数的大小,而不是一个单一的字节。这种操作对数组最有用,因为数组包含的数据是类型一致且在内存中连续的。

例如,假设你在自由存储区声明了一个整数数组:

int* myArray { new int[8] };

你可能已经熟悉了以下用于设置索引为2的值的语法:

myArray[2] = 33;

通过使用指针算术,你也可以使用以下等效的语法,该语法获取到myArray“向前两个整数”处的内存的指针,然后解引用它以设置该值:

*(myArray + 2) = 33;

作为访问单个元素的另一种语法,指针算术看起来可能不太吸引人。但其真正的力量在于,像myArray+2这样的表达式仍然是一个指向整数的指针,因此可以表示一个更小的整数数组。

让我们通过一个使用宽字符串的例子来看看。宽字符串支持所谓的Unicode字符,以表示例如日语字符串。wchar_t类型是一个可以容纳这种Unicode字符的字符类型,并且通常比char要大;也就是说,它不仅仅是一个字节。要告诉编译器一个字符串字面量是一个宽字符串字面量,可以在其前面加上一个L

例如,假设你有以下宽字符串:

const wchar_t* myString { L"Hello, World" };

进一步假设你有一个函数,该函数接受一个宽字符串并返回一个包含输入字符串大写版本的新字符串:

wchar_t* toCaps(const wchar_t* text);

请记住,C风格的字符串是以零结尾的,即它们的最后一个元素包含\0。因此,没有必要在函数中添加一个大小参数来指定输入字符串的长度。该函数只需不断地迭代字符串的各个字符,直到遇到\0字符为止。

通过将myString传递给toCaps()函数,你可以将其全部转换为大写。然而,如果你只想部分地大写化myString,你可以使用指针算术来仅引用字符串的后一部分。下面的代码通过仅向指针加7来调用toCaps()函数,以处理宽字符串中的“World”部分,尽管wchar_t通常超过1个字节:

toCaps(myString + 7);

另一个有用的指针算术应用涉及到减法。从同一类型的另一个指针中减去一个指针会给你两个指针之间指向类型的元素数量,而不是它们之间的绝对字节数。

自定义内存管理

在你将遇到的99%(有人可能会说100%)的情况中,C++中的内置内存分配功能是足够的。在幕后,newdelete完成了以适当大小的块分配内存、维护可用内存区域列表以及在删除时将内存块释放回该列表的所有工作。但是,当资源约束非常紧张,或者在非常特殊的条件下,例如管理共享内存,实施自定义内存管理可能是一个可行的选项。不用担心,这并不像听起来那么可怕。

基本上,自己管理内存意味着类会分配一大块内存,并根据需要将该内存分配出去。这种方法有什么好处呢?管理自己的内存可能会减少开销。当你使用new来分配内存时,程序还需要预留一小部分空间以记录分配了多少内存。这样,当你调用delete时,可以释放适当数量的内存。对于大多数对象,开销比分配的内存小得多,因此影响甚微。然而,对于小对象或有大量对象的程序,开销可能会产生影响。当你自己管理内存时,你可能会提前知道每个对象的大小,因此你可能能够避免每个对象的开销。对于大量的小对象来说,差异可能是巨大的。

执行自定义内存管理需要重载newdelete操作符。

垃圾收集

在支持垃圾收集的环境中,程序员很少(如果有的话)明确释放与对象关联的内存。相反,不再有任何引用的对象将在某个时候被运行时库自动清理。垃圾收集没有像在C#和Java中那样内置到C++语言中。在现代C++中,你使用智能指针来管理内存,而在遗留代码中,你将看到通过newdelete在对象级别进行内存管理。

诸如shared_ptr这样的智能指针提供了与垃圾收集内存非常相似的东西;也就是说,当某一资源的最后一个shared_ptr实例被销毁时,该资源也会在那个时刻被销毁。在C++中实现真正的垃圾收集是可能但不容易的,但释放自己从释放内存的任务中可能会引入新的问题。

标记-清除垃圾收集

一种垃圾收集的方法被称为“标记-清除”(Mark and Sweep)。在这种方法下,垃圾收集器会周期性地检查程序中的每一个指针,并标注哪些内存仍然在使用中。在周期结束时,任何没有被标记的内存被认为是不再使用的,并会被释放。在C++中实现这样的算法并不简单,如果做错了,可能比使用delete更容易出错!

尽管在C++中已经有了安全且简单的垃圾收集机制的尝试,但即使有了完美的C++垃圾收集实现,也不一定适用于所有应用程序。垃圾收集的缺点包括:

  • 当垃圾收集器正在运行时,程序可能变得无响应。
  • 在使用垃圾收集器的情况下,你会遇到所谓的“非确定性析构函数”。因为一个对象在被垃圾收集之前不会被销毁,所以析构函数在对象离开其作用域时不会立即执行。这意味着,由析构函数完成的资源清理(例如关闭文件、释放锁等)直到未来某个不确定的时间才会被执行。

编写垃圾收集机制是非常困难的。你很可能会做错,而且很可能会很慢。因此,如果你确实想在你的应用程序中使用垃圾收集内存,我强烈建议你研究现有的专门的垃圾收集库,并重用它们。

对象池

垃圾收集就像是为野餐购买盘子,并将用过的盘子留在院子里,以便某人在某个时候将它们捡起来并扔掉。肯定有更环保的内存管理方法。对象池就是回收的等价物。你购买了一定数量的盘子,使用过一个盘子后,你将其清洗,以便以后可以再次使用。

对象池是理想的解决方案,适用于你需要在一段时间内多次使用相同类型的多个对象,并且每次创建都会产生开销的情况。

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

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

相关文章

GB/T 29734.2-2013 铝塑复合门窗检测

铝合金门窗是指采用铝塑复合型材制作框、扇杆件结构的门、窗的总称,根据门窗开启形式的不同,可分为固定窗、平开窗、推拉窗,悬窗等。 GB/T 29734.2-2013 铝塑复合门窗检测项目 测试项目 测试标准 外观质量 GB/T 29734.2 尺寸 GB/T 2973…

面试经验——面试项目准备工作

摘要 本博文主要是分享个人在面试中对于项目思考,希望帮助大家能够面试中能够很好的介绍和分享自己的项目。在面试官心中留下一个好印象,希望你能拿到自己满意的offer。 一、面试项目常见问题 1.1 工作经历中,最优技术挑战/亮点的事情是什…

Elasticsearch聚合----aggregations的简单使用

文章目录 Getting started1、搜索 address 中包含 mill 的所有人的年龄分布以及平均年龄,但不显示这些人的详情2、size0不展示命中记录,只展示聚合结果3、按照年龄聚合,并且请求这些年龄段的这些人的平均薪资4、查出所有年龄分布,…

【Android Studio】工程中文件Annotate with Git Blame 不能点击

问题描述 工程文件中想要查看代码提交信息但是相关按钮不可点击 解决方法 Android Studio -> Preferences -> Version Control-> 在Unregistered roots里找到你想要的工程文件 点击左上角➕号 然后右下角Apply即可

Python分享之多进程初步 (multiprocessing包)

我们已经见过了使用subprocess包来创建子进程,但这个包有两个很大的局限性:1) 我们总是让subprocess运行外部的程序,而不是运行一个Python脚本内部编写的函数。2) 进程间只通过管道进行文本交流。以上限制了我们将subprocess包应用到更广泛的…

【异常】理解Java中的异常处理机制

标题:理解Java中的异常处理机制 摘要: 异常处理是Java编程中的重要概念之一,它可以帮助开发者识别和处理程序运行过程中的错误和异常情况。本文将深入探讨Java中的异常处理机制,包括异常的分类、异常处理的语法和最佳实践。通过示…

Filter过滤器和Listener监听器

2023.10.26 Filter过滤器 过滤器,顾名思义就是对事物进行过滤的。Web中的过滤器,就是对请求进行过滤,我们使用过滤器,就可以对请求进行拦截,然后做相应的处理,实现许多特殊功能。如登录控制,权…

uniapp开发小程序—picker结合后台数据实现二级联动的选择

一、效果图 二、完整代码 <template><view><picker mode"multiSelector" change"bindMultiPickerChange" columnchange"bindMultiPickerColumnChange":value"multiIndex" :range"multiArray"><view c…

基于FPGA的电风扇控制器verilog,视频/代码

名称&#xff1a;基于FPGA的电风扇控制器verilog 软件&#xff1a;QuartusII 语言&#xff1a;Verilog 代码功能&#xff1a; 基于FPGA的电风扇控制器 运用 EDA SOPO实验开发系统设计一个基于FPGA的电风扇定时开关控制器,能实现手动和自动模式之间的切换。要求: (1)KI为电…

【Gensim概念】03/3 NLP玩转 word2vec

第三部分 对象函数 八 word2vec对象函数 该对象本质上包含单词和嵌入之间的映射。训练后&#xff0c;可以直接使用它以各种方式查询这些嵌入。有关示例&#xff0c;请参阅模块级别文档字符串。 类型 KeyedVectors 1&#xff09; add_lifecycle_event(event_name, log_level2…

@AutoConfigurationPackage注解类

包名package org.springframework.boot.autoconfigure 方法 String[] basePackages() 向AutoConfigurationPackages中注册的基本包&#xff0c;使用basePackageClasses作为基于字符串的包的类型安全替代方案 Class<?>[] basePackageClasses() 键入basePackage…

APP破解去广告

1.修改图标和名称 名称直接改 找到图标在进去把他替换掉 2.修改app包名实现分身 修改包名实现app分身_Tian翊的博客-CSDN博客 3.修改资源去广告 安卓逆向006之修改APK资源去广告_修改安装包去除app内广告-CSDN博客 打开模拟器后在cmd命令行输入adb devices连接上 在模拟器中…

【多线程】探索Java中的多线程编程

标题&#xff1a;探索Java中的多线程编程 摘要&#xff1a; Java是一种广泛使用的编程语言&#xff0c;具有强大的多线程编程能力。本文将深入探讨Java中的多线程编程&#xff0c;包括线程的创建、同步与互斥、线程池的使用以及常见的多线程编程模式。通过示例代码和详细解释&…

每日一练——返回链表的中间结点

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇:Solitary-walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”。…

【单元测试】--维护和改进单元测试

一、持续维护单元测试 持续维护单元测试是确保它们继续有效的关键。以下是一些方法来保持单元测试的可维护性&#xff1a; 集成单元测试到持续集成流程&#xff1a;将单元测试包括在持续集成&#xff08;CI&#xff09;流程中&#xff0c;确保它们在每次代码更改后都自动运行…

Dockerfile文件自动化生成R4L镜像

Dockerfile文件自动化生成R4L镜像的步骤 1、安装Docker&#xff1a;2、使用Dockerfile一键生成镜像&#xff1a;3、查看生成的Docker镜像&#xff1a;4、删除Docker镜像&#xff1a;5、生成Docker容器&#xff1a;6、查看容器7、删除容器 1、安装Docker&#xff1a; curl -fsS…

sqoop和flume简单安装配置使用

1. Sqoop 1.1 Sqoop介绍 Sqoop 是一个在结构化数据和 Hadoop 之间进行批量数据迁移的工具 结构化数据可以是MySQL、Oracle等关系型数据库 把关系型数据库的数据导入到 Hadoop 与其相关的系统 把数据从 Hadoop 系统里抽取并导出到关系型数据库里 底层用 MapReduce 实现数据 …

如何巧妙告知家长成绩分数

如何让学生和家长们查询期中考试成绩,一直是让许多老师都头疼不已的问题。今天我就来交给大家怎么解决这个问题。 我们先了解一下成绩查询系统是什么。在互联网高度发达的今天&#xff0c;成绩查询系统已经不再是学校的专属&#xff0c;而是可以通过网络平台进行操作的一种工具…

LVS负载均衡(LVS简介、三种工作模式、十种调度算法)

LVS简介 LVS&#xff08;Linux Virtual Server&#xff09;是一种基于Linux内核的高可用性负载均衡软件。它通过将客户端请求分发到多个后端真实服务器&#xff0c;提高系统性能和可靠性。LVS支持多种调度算法&#xff0c;如轮询、最少连接、源地址哈希等&#xff0c;用于决定…

利用MATLAB创建栅格地图(代码可复制)

先做一个声明&#xff1a;文章是由我的个人公众号中的推送直接复制粘贴而来&#xff0c;因此对智能优化算法感兴趣的朋友&#xff0c;可关注我的个人公众号&#xff1a;启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法&#xff0c;经典的&#xff0c;或者是近几年…