详解CC++内存管理(new和delete)

news2024/11/25 18:40:12

文章目录

  • 写在前面
  • 1. C&C++内存分布
  • 2. C语言中动态内存管理方式:malloc/calloc/realloc/free
  • 3. C++内存管理方式(语法)
    • 3.1 new/delete操作内置类型
    • 3.2 new和delete操作自定义类型
  • 4. new和delete的实现原理
    • 4.1 operator new与operator delete函数
    • 4.2 实现原理
      • 4.2.1 内置类型
      • 4.2.2 自定义类型
  • 5. 定位new表达式(placement-new)(了解)

写在前面

本篇文章先讨了C/C++程序中的内存分布,并简单介绍了各个内存段的作用和特点。在此基础上,又着重讨论了C语言和C++语言中的动态内存管理方式,包括malloc()、free()等C语言函数以及new和delete等C++语言操作符。进一步探讨了operator new和operator delete函数在C++中的作用和使用方式,并揭示了new和delete的实现原理。最后,对定位new表达式(placement-new)进行了解析,介绍了它在特定场景下的应用及实现原理。

1. C&C++内存分布

在这里插入图片描述
上面图片介绍了C/C++程序中的内存分布,并详细介绍了各个内存段的作用和特点。
下面我们通过一段代码和相关问题,来深入理解C/C++程序中的内存分布。

int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
 static int staticVar = 1;
 int localVar = 1;
 int num1[10] = { 1, 2, 3, 4 };
 char char2[] = "abcd";
 const char* pChar3 = "abcd";
 int* ptr1 = (int*)malloc(sizeof(int) * 4);
 int* ptr2 = (int*)calloc(4, sizeof(int));
 int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
 free(ptr1);
 free(ptr3);
/* 1. 选择题:
   选项: A.栈  B.堆  C.数据段(静态区)  D.代码段(常量区)
   globalVar在哪里?__c__   staticGlobalVar在哪里?__c__
   staticVar在哪里?__c__   localVar在哪里?__a__
   num1 在哪里?__a__
   
   char2在哪里?____       *char2在哪里?___
   pChar3在哪里?____      *pChar3在哪里?____
   ptr1在哪里?____        *ptr1在哪里?____
2. 填空题:
   sizeof(num1) = ____;  
    sizeof(char2) = ____;      strlen(char2) = ____;
   sizeof(pChar3) = ____;      strlen(pChar3) = ____;
   sizeof(ptr1) = ____;
3. sizeof 和 strlen 区别?
}*/

在这里插入图片描述

2. C语言中动态内存管理方式:malloc/calloc/realloc/free

C语言中动态内存管理方式:malloc/calloc/realloc/free的详细介绍,有兴趣的读者可以参考之前写的文章:动态内存管理(malloc calloc realloc free)— C语言[点击蓝色字体跳转],这里就不在赘述。

3. C++内存管理方式(语法)

C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦。例如:在C语言中使用 malloc 和 free 进行内存分配和释放时,需要手动计算申请内存空间的大小,并且需要对返回值进行强制类型转换,容易出错。

因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。在C++中,它们不仅可以用于内置类型(例如 int、double 等),还可以用于自定义类型(例如类、结构体等)。下面我们来一一介绍。

3.1 new/delete操作内置类型

int main()
{
	// 动态申请一个int类型的空间
	int* pa = new int;
	// 动态申请一个int类型的空间并初始化为10
	int* pb = new int(10);
	// 动态申请10个int类型的空间
	int* nums1 = new int[10];
	// 动态申请10个int类型的空间,并用{1, 2, 3, 4}初始化,不完全初始化,剩下的默认初始化为0。
	int* nums2 = new int[10] {1, 2, 3, 4};

	delete pa;
	delete pb;
	delete[] nums1;
	delete[] nums2;

	return 0;
}

在这里插入图片描述

注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意:匹配起来使用。

3.2 new和delete操作自定义类型

class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a = 0)" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};

int main() 
{
	//malloc 和 new 最大的区别是对于自定义类型除了会开空间以外,new 还会调用构造函数完成对对象的初始化
	A* pa1 = new A;
	A* pa2 = (A*)malloc(sizeof(A));

	//free 和 delete 最大的区别是对于自定义类型除了会释放空间以外,还会调用析构函数来完成对对象中资源的清理
	delete pa1;
	free(pa2);

	return 0;
}

在这里插入图片描述
注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。 new/delete 和 malloc/free对于内置类型 是几乎是一样的,只是用法不同罢了。

4. new和delete的实现原理

4.1 operator new与operator delete函数

new和delete是用户进行动态内存申请和释放的操作符operator new 和operator delete
系统提供的全局函数new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
在这里插入图片描述
通过上述两个全局函数的实现知道,operator new 实际也是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的。
operator new 和operator delete是系统提供的全局函数,因此可以显示的调用,平常不会这样使用(了解)。
在这里插入图片描述

4.2 实现原理

4.2.1 内置类型

如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:

  1. new/delete申请和释放的是单个元素的空间,new[]和delete[]申请和释放的是连续空间。
    在这里插入图片描述

  2. new在申请空间失败时会抛异常,malloc会返回NULL。
    在这里插入图片描述

4.2.2 自定义类型

new的原理:

  1. 调用operator new函数申请空间。
  2. 在申请的空间上执行构造函数,完成对象的构造。
    在这里插入图片描述

delete的原理:

  1. 在空间上执行析构函数,完成对象中资源的清理工作。
  2. 调用operator delete函数释放对象的空间。
    在这里插入图片描述

new T[N]的原理:

  1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请。
  2. 在申请的空间上执行N次构造函数。
    在这里插入图片描述

delete[]的原理:

  1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理。
  2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间。
    在这里插入图片描述

5. 定位new表达式(placement-new)(了解)

定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。
在这里插入图片描述
至此,本片文章就结束了,若本篇内容对您有所帮助,请三连点赞,关注,收藏支持下。

创作不易,白嫖不好,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!

如果本篇博客有任何错误,请批评指教,不胜感激 !!!
在这里插入图片描述

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

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

相关文章

【MySQL】学习外键约束处理员工数据

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-g4glZPIY0IKhiTfe {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

STM32—DHT11温湿度传感器

文章目录 一.温湿度原理1.1 时序图 二.代码 一.温湿度原理 1.1 时序图 (1).下图一是DHT11总的时序图。 (2).图二对应图一的左边黑色部分&#xff0c;图三对应图一的绿色部分&#xff0c;图四的左部分图对应图一的红色部分&#xff0c;图四的右部分对应图一的黄色部分。 (3)…

计算机组成原理(1)----主存储器

目录 1.基本半导体元件及原理 2.寻址 1.基本半导体元件及原理 一个主存储器可以分为存储器&#xff0c;MAR&#xff08;地址寄存器&#xff09;和MDR&#xff08;数据寄存器&#xff09;&#xff0c;这三个部件由在时序控制逻辑的控制下工作 其中存储体用来存放二进制数据0和…

[BIZ-缓存] - 3.金融交易系统缓存架构设计

1. 前置文章 [BIZ] - 1.金融交易系统特点https://blog.csdn.net/besthezhaowen/article/details/136118133 [缓存] - 1.缓存共性问题https://blog.csdn.net/besthezhaowen/article/details/136111466 [缓存] - 2.分布式缓存重磅中间件 Redis-CSDN博客文章浏览阅读1.4k次&…

docker (一)-简介

1.什么是docker Docker 是一个开源的应用容器引擎&#xff0c;由于docker影响巨大&#xff0c;今天也用"Docker" 指代容器化技术。 2.docker的优势 一键部署&#xff0c;开箱即用 容器使用基于image镜像的部署模式&#xff0c;image中包含了运行应用程序所需的一…

【Java程序员面试专栏 分布式中间件】ElasticSearch 核心面试指引

关于ElasticSearch 部分的核心知识进行一网打尽,包括ElasticSearch 的基本概念,基本架构,工作流程,存储机制等,通过一篇文章串联面试重点,并且帮助加强日常基础知识的理解,全局思维导图如下所示 基础概念 从数据分类入手,考察全文索引的基本概念 现实世界中数据有哪…

【教程】Kotlin语言学习笔记(二)——数据类型(持续更新)

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 【Kotlin语言学习】系列文章 第一章 《认识Kotlin》 第二章 《数据类型》 文章目录 【Kotlin语言学习】系列文章一、基本数据…

机器学习和统计学的区别?

1、本质区别&#xff1a; 目标&#xff1a;机器学习的核心目标是建立一个可以自动学习和改进的模型&#xff0c;以预测未知数据。它更关注结果的准确性和模型的泛化能力&#xff0c;通常不关心模型是否可以解释。而统计学的目标是探究变量之间的关系&#xff0c;理解数据的内在…

Python数据科学:Scikit-Learn机器学习

4.1Scikit-Learn机器学习 Scikit-Learn使用的数据表示&#xff1a;二维网格数据表 实例1&#xff1a;通过Seaborn导入数据 def skLearn():scikit Learn基本介绍:return:import seaborn as sns#导入Iris数据集#注&#xff1a;一般网络访问不了iris sns.load_dataset(iris)ir…

Spring Boot 笔记 020 redis集成

1.1 安装redis Windows 下 Redis 安装与配置 教程_redis windows-CSDN博客 2.1 引入redis坐标 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency> 2.2 配置…

144.【Activiti 7】

Activiti 7 工作流 (一)、工作流程1.概念2.工作流系统3.适用行业4.具体应用5.实现方式 (二)、Activiti7概述1.介绍(1).BPM 介绍(2).BPM软件(3). BPMN 2.使用步骤(1).部署activiti(2).流程定义(3).流程定义部署(4).启动一个流程实例(5).用户查询待办任务(Task)(6).用户办理任务(…

第13讲创建图文投票

创建图文投票实现 图文投票和文字投票基本一样&#xff0c;就是在投票选项里面&#xff0c;多了一个选项图片&#xff1b;、 <view class"option_item" v-for"(item,index) in options" :key"item.id"><view class"option_input&…

如何在JavaScript中使用大于和小于运算符

在你的 JavaScript 程序中&#xff0c;你经常需要比较两个值&#xff0c;以确定一个是否大于另一个或小于另一个。这就是大于和小于运算符派上用场的地方。 在本文中&#xff0c;我们将通过代码示例更详细地介绍如何使用这些运算符。 &#xff08;本文内容参考&#xff1a;ja…

Mysql中关于on,in,as,where的区别

目录 Mysql on,in,as,where的区别 Mysql语句问题解决 1、left join数据筛选问题 2、相同数据重复筛选使用问题 3、根据某个字段排序取每个类别最后三条数据或前三条数据 4、业务逻辑书写位置问题 5、查找另一表内和本表相关字段的数量 6、关于union的使用 7、limit的巧…

Ubuntu如何设置成中文

1、右上角点击&#xff08;音量图标和电池图标位置&#xff09;&#xff0c;选择“Settings”&#xff08;设置&#xff09;。 2、左侧选择“Region & Language”&#xff08;区域与语言&#xff09;&#xff0c;然后选择“Manage Installed Languages”&#xff08;管理已…

测试开发-2-概念篇

文章目录 衡量软件测试结果的依据—需求1.需求的概念2.从软件测试人员角度看需求3.为什么需求对软件测试人员如此重要4.如何才可以深入理解被测试软件的需求5.测试用例的概念6.软件错误&#xff08;BUG&#xff09;的概念7.开发模型和测试模型8.软件的生命周期9.瀑布模型&#…

中科大计网学习记录笔记(十一):CDN

前言&#xff1a; 学习视频&#xff1a;中科大郑烇、杨坚全套《计算机网络&#xff08;自顶向下方法 第7版&#xff0c;James F.Kurose&#xff0c;Keith W.Ross&#xff09;》课程 该视频是B站非常著名的计网学习视频&#xff0c;但相信很多朋友和我一样在听完前面的部分发现信…

Qt 的准备知识

文章目录 1. Qt 背景介绍2. 搭建 Qt 开发环境3. 认识 Qt Creator3.1 main.cpp3.2 widget.h3.3 widget.cpp3.4 Forms3.5 .pro文件 1. Qt 背景介绍 Qt 是⼀个 跨平台的 C 图形用户界面应用程序框架 。它为应用程序开发者提供了建立艺术级图形界⾯所需的所有功能。它是完全⾯向对…

SAP MM学习笔记42 - 特殊调达流程 - 受托品(寄售)

上一章讲了 外注加工的知识。 详细可以参考如下链接。 SAP MM学习笔记41 - 特殊调达流程 - 外注加工-CSDN博客 咱们继续学习特殊调达流程。 本章主要讲受托品。 1&#xff0c;什么是受托品 &#xff08;寄售&#xff09; 仕入先提供的商品&#xff0c;商品是放在你公司了&a…

Python爬虫——解析库安装(1)

目录 1.lxml安装2.Beautiful Soup安装3.pyquery 的安装 我创建了一个社区&#xff0c;欢迎大家一起学习交流。社区名称&#xff1a;Spider学习交流 注&#xff1a;该系列教程已经默认用户安装了Pycharm和Anaconda&#xff0c;未安装的可以参考我之前的博客有将如何安装。同时默…