【c++】——类和对象(下) ——内存管理

作者:chlorine

专栏:c++专栏

目录

💻 C/C++内存分布

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

​编辑

💻C++内存管理方式

👉new/delete操作内置类型

👉new和delete操作自定义类型

💻operator new与operator delete函数(重要点进行讲解)

💻new和delete的实现原理

👉内置类型

👉 自定义类型

💻常见面试题

malloc/free和new/delete的区别


💻 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_

上面的几个变量的位置在哪大家肯定很清楚,下面几个变量就有些难度了。

选项 : A.栈  B.堆  C.数据段(静态区)  D.代码段(常量区)

  • char2在哪里?__A__ * char2在哪里?_A__

字符串默认是常量字符串存储常量区,而char2是开辟的数组存储在栈区
将字符串拷贝给数组(数组是初始化)。但是我们要知道数组名是数组首元素的地址
char2是数组首元素的地址,对数组首元素的地址解引用是'a'不再常量区,而是栈区。因为字符串已经拷贝给数组,数组在栈区那么字符串就在常量区。所以这里是大家出错的地方,我一开始也选的是D,但是我们要知道字符串虽然存储在常量区,但是我们要给新开辟的数组初始化,就得给堆区的字符串拷贝给数组。

选项 : A.栈  B.堆  C.数据段(静态区)  D.代码段(常量区)

  • pChar3在哪里?_A_    * pChar3在哪里?_D__
  •  const char* pChar3 = "abcd";

pChar3是指针变量,存储在栈区,这是毋庸置疑的。字符串默认是常量字符串存储在常量区。pchar3是指向常量区"abcd\0"的地址,*pchar3是对常量区的"abcd\o"字符串解引用,找到字符串中a字符的,所以在字符串在哪*pchar就在哪。所以*pChar3存储在常量区。

选项 : A.栈  B.堆  C.数据段(静态区)  D.代码段(常量区)

  • ptr1在哪里?_A___ * ptr1在哪里?__B__
  •  int* ptr1 = (int*)malloc(sizeof(int) * 4);

ptr1是指针变量,在栈区,而表达式后面malloc其实是在堆上malloc个空间,*ptr1指向那块开辟的空间并对其解引用,找到那块空间,所以在*ptr1在堆区。


2. 填空题:

 int num1[10] = { 1, 2, 3, 4 };
 char char2[] = "abcd";

 const char* pChar3 = "abcd";

 int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);


sizeof(num1) = _40___;
sizeof(char2) = _5___;      strlen(char2) = __4__;
sizeof(pChar3) = __4/8__;     strlen(pChar3) = _4/8___;    指针4/8字节
sizeof(ptr1) = _4/8___;

【说明】
  • 1. 又叫堆栈--非静态局部变量/函数参数/返回值等等,栈是向下增长的。
  • 2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口
  • 创建共享共享内存,做进程间通信。(Linux课程如果没学到这块,现在只需要了解一下)
  • 3. 用于程序运行时动态内存分配,堆是可以上增长的。
  • 4. 数据段--存储全局数据和静态数据。
  • 5. 代码段--可执行的代码/只读常量。

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

malloc 

calloc 

realloc 

free 


💻C++内存管理方式

C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因 此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理

👉new/delete操作内置类型

voidTest()
{
  // 动态申请一个int类型的空间
  int*ptr4=new int;
  
  // 动态申请一个int类型的空间并初始化为10   
    int*ptr5=new int(10);
  
  // 动态申请10个int类型的空间
  int*ptr6=new int[10];


 delete ptr4;
  delete ptr5;
  delete[] ptr6;
}

如果我们想申请3个int类型的空间,并初始化1,2,3.

这样显然报错,给多个申请空间初始化,需要用{}来初始化。

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


👉newdelete操作自定义类型

class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}
	~A()
	{
		cout << "~A():" << this << endl;
	}
private:
	int _a;
};
int main()
{
	// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间
	//还会调用构造函数和析构函数
	A* p1 = (A*)malloc(sizeof(A));
	A* p2 = new A(1);
	free(p1);
	delete p2;
	return 0;
}

注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与
free不会

💻operator newoperator delete函数(重要点进行讲解)

new delete 是用户进行 动态内存申请和释放的操作符 operator new operator delete
系统提供的 全局函数 new 在底层调用 operator new 全局函数来申请空间, delete 在底层通过
operator delete 全局函数来释放空间。

  • operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间 失败,尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
  • operator delete: 该函数最终是通过free来释放空间的

💻newdelete的实现原理

👉内置类型

如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申 请空间失败时会抛异常,malloc会返回NULL。

👉 自定义类型

  • 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来释放空间

💻常见面试题

malloc/free和new/delete的区别

  • 1. malloc和free是函数,new和delete是操作符
  • 2. malloc申请的空间不会初始化,new可以初始化
  • 3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可,
  • 如果是多个对象,[]中指定对象个数即可
  • 4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
  • 5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常

特性 + 用法(上面5点)

  • 6. 申请自定义类型对象时,malloc / free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

别心急,任何事

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

makefile 学习(5)完整的makefile模板

参考自&#xff1a; (1&#xff09;深度学习部署笔记(二): g, makefile语法&#xff0c;makefile自己的CUDA编程模板(2&#xff09;https://zhuanlan.zhihu.com/p/396448133(3) 一个挺好的工程模板&#xff0c;(https://github.com/shouxieai/cpp-proj-template) 1. c 编译流…

Linux加强篇004-Vim编辑器与Shell命令脚本

目录 前言 1. Vim文本编辑器 1.1 编写简单文档 1.2 配置主机名称 1.3 配置网卡信息 1.4 配置软件仓库 2. 编写Shell脚本 2.1 编写简单的脚本 2.2 接收用户的参数 2.3 判断用户的参数 3. 流程控制语句 3.1 if条件测试语句 3.2 for条件循环语句 3.3 while条件循环语…

深入浅出 Linux 中的 ARM IOMMU SMMU II

SMMU 驱动中的系统 I/O 设备探测 要使系统 I/O 设备的 DMA 内存访问能通过 IOMMU&#xff0c;需要将系统 I/O 设备和 IOMMU 设备绑定起来&#xff0c;也就是执行 SMMU 驱动中的系统 I/O 设备探测。总线发现系统 I/O 设备并和对应的驱动程序绑定&#xff0c;与 IOMMU 设备驱动程…

死锁是什么?死锁是如何产生的?如何破除死锁?

1. 死锁是什么 多个线程同时被阻塞&#xff0c;它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞&#xff0c;因此程序不可能正常终止。 2. 死锁的三种典型情况 一个线程, 一把锁, 是不可重入锁, 该线程针对这个锁连续加锁两次, 就会出现死锁. 两个线程…

Java多态:多态多态,多么变态

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、重写1、重写的规则2、重写与重载的区别 二、多态1、多态的概念2、多态的实现3、向上转移和向下转型Ⅰ、向上转型Ⅱ、向下转…

蓝桥杯官网算法赛(蓝桥小课堂)

问题描述 蓝桥小课堂开课啦&#xff01; 海伦公式&#xff08;Herons formula&#xff09;&#xff0c;也称为海伦-秦九韶公式&#xff0c;是用于计算三角形面积的一种公式&#xff0c;它可以通过三条边的长度来确定三角形的面积&#xff0c;而无需知道三角形的高度。 海伦公…

BART 并行成像压缩感知重建:联合重建

本文使用 variavle-density possion-disc 采样的多通道膝盖数据进行并行重建和压缩感知重建。 0 数据欠采样sampling pattern 1 计算ESPIRiT maps % A visualization of k-space dataknee = readcfl(data/knee); ksp_rss = bart(rss 8, knee);ksp_rss = squeeze(ksp_rss); figu…

11 月 25 日 ROS 学习笔记——3D 建模与仿真

文章目录 前言一、在 ROS 中自定义机器人的3D模型1. 在 rviz 里查看3D模型2. xacro 二、Gazebo1. urdf 集成 gazebo2. 综合应用1). 运动控制及里程计2). 雷达仿真3). 摄像头信息仿真4). kinect 深度相机仿真5). 点云 前言 本文为11 月 25 日 ROS 学习笔记——3D 建模与仿真&am…

求集合的笛卡尔乘积

求集合的笛卡尔乘积 一&#xff1a;【实验目的】二&#xff1a;【实验内容】三&#xff1a;【实验原理】四&#xff1a;代码实现&#xff1a; 一&#xff1a;【实验目的】 通过编实现给定集合A和B的笛卡尔积CAA,DAB,EBA,FAAB,GA(A*B&#xff09;. 二&#xff1a;【实验内容】…

迈巴赫S480升级电动后门 手势控制开关 更加方便

安装了电动后门的迈巴赫S480&#xff0c;从原来的触摸门把手和门内拉手开关门&#xff0c;增加了钥匙控制、前排显示屏控制、后门按键开关控制、后排娱乐屏控制等多种开关门方式&#xff0c;将一个待客之礼体现出多种不一样的尊贵感受。 中控显示屏由驾驶者控制&#xff0c;可以…

1.4 8位加法器

1.半加器 2.全加器 半加器: 完整模拟1位加法 1.A,B 接受端,接受1或0 , 2个电信号 2.异或门 做为结果: 1^10, 0^00, 1^01, 0^11 与编程中的: 异或一致 3.与门 做为进位: 1&11,1&00,0&10, 0&01 与编程中的: 与一致 4.半加器实现1位的加法运算,比如:A端: …

图书馆管理系统源码(Java)

Book包->内含Book类与BookList类 Book类 用于初始化图书并对其进行操作 BookList类 用于存放多本图书 Book类 package Book;public class Book {private String name;private String author;private int price;private String type;private boolean isBorrow;//写一个…

6.11左叶子之和(LC404-E)

用java定义树&#xff1a; public class TreeNode {int val;TreeNode left;TreeNode right; //一个空构造方法TreeNode()&#xff0c;用于初始化节点的默认值。TreeNode() {} //一个构造方法TreeNode(int val)&#xff0c;用于初始化节点的值&#xff0c;并设置默认的左右子节…

【Unity3D】MAX聚合广告SDK——Pangle广告接入

Pangle, App Monetization Simplified 注册 登录 创建应用 创建广告单元 将其应用ID和广告ID关联到MAX广告。 下载Pangle Unity Plugin包&#xff0c;新建一个空工程&#xff08;很重要&#xff09; Unity版本2019.4.0f1 gradle plugin 4.2.0 gradle版本6.7.1 build_tools 34.…

el-uploader同一文件无法上传问题

在上传成功和失败的回调方法中&#xff0c;吊用一下clearFiles方法。 this.$refs.upload.clearFiles();

Node.js入门指南(四)

目录 express框架 express介绍 express使用 express路由 express 响应设置 中间件 路由模块化 EJS 模板引擎 express-generator hello&#xff0c;大家好&#xff01;上一篇文章我们介绍了Node.js的模块化以及包管理工具等知识&#xff0c;这篇文章主要给大家分享Nod…

c语言中指针详解

内存与地址 1.地址的概念 众所周知数据需要在内存中读取&#xff0c;那么我们当我们需要找这个内存时该怎么办&#xff1f;其实在计算机中每个内存单元都有一个编号&#xff0c;有了这个编号CPU可以快速找到内存空间&#xff0c;在这里我们将这个编号叫做地址&#xff0c;在c…

企业计算机服务器中了360勒索病毒怎么办,360勒索病毒解密文件恢复

计算机技术的不断发展&#xff0c;为企业的生产运营提供了极大便利&#xff0c;不仅提升了办公效率&#xff0c;还促进了企业的发展。企业计算机在日常工作中一定加以防护&#xff0c;减少网络威胁事件的产生&#xff0c;确保企业的生产生产运营。最近&#xff0c;网络上的360后…

nodejs+vue+python+PHP+微信小程序-健身俱乐部在线管理平台的设计与实现-安卓-计算机毕业设计

随着经济的发展、财富的累积&#xff0c;人们生活水平、生活质量大幅度提高&#xff0c;生活环境得到明显改善&#xff0c;但是竞争激烈、人们生活压力大、生活节奏快加上饮食习惯和生活方式不合理导致国内 亚健康人群逐年增多。统计数据表明当前我国亚健康人群比例已经超过了7…

vscode导入STM32CubeIDE工程文件夹未定义警告清除方法

0 前言 在我们使用vscode去编辑STM32CubeIDE的工程文件时&#xff0c;经常会出现一些类型未定义、头文件路径无效的问题&#xff0c;无法正常使用且非常影响观感。本文介绍如何设置vscode导入的STM32CubeIDE配置文件&#xff0c;解决这一问题。 1 vscode导入STM32CubeIDE工程…