c++ - 空间申请和释放 new/delete

news2024/12/22 16:31:45

文章目录

    • 一、c/c++内存分布
    • 二、new/delete 的使用
    • 三、malloc/free 和 new/delete 的对比
    • 四、new/delete 的实现原理
    • 五、匹配问题


一、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);
}
选项: A.栈  B.堆  C.数据段(静态区)  D.代码段(常量区)  

1、 globalVar在哪里?____ 2、staticGlobalVar在哪里?____ 3、staticVar在哪里?____ 4、localVar在哪里?____ 5、num1 在哪里?____ 6、char2在哪里?____ 7、*char2在哪里?___ 8、pChar3在哪里?____ 9、*pChar3在哪里?____ 10、ptr1在哪里?____ 11、*ptr1在哪里?____
答案:1-5 CCCAA 6-11AAADAB

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/4ea571fe70e04481baf829bd12b580aa.png

说明:

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

二、new/delete 的使用

关键字: new
作用:申请空间
关键字:delete
作用:释放空间

如:


//new 和 delete的使用
int main()
{
	//new 申请一个变量空间	
	int* p = new int;	//(类型指针) 指针名 = new 类型

	//delete 释放一个变量空间	// delete 释放的指针
	delete p;

	//new 申请一个数组空间	
	int* pp = new int[10];	//(类型指针) 指针名 = new 类型[(申请的数组大小)]

	//delete 释放一块数组的空间
	delete[]pp;	//delete [] 释放的指针

	return 0;
}

注意:
释放数组的时候 delete 一定要和 [ ] 配对使用,不然只会释放该指针指向的第一个位置,这样就会造成内存泄漏。

三、malloc/free 和 new/delete 的对比

1、mallocfree是库函数,而newdelete是运算符(类似sizeof 属于运算符而不属于库函数) 。

2、malloc使用比new更复杂
如:

int main()
{
	//malloc申请一个变量空间
	int* p = (int*)malloc(sizeof(int));

	//new申请一个变量空间
	int* pp = new int;

	return 0;
}

在这里插入图片描述

3、malloc 不能对申请的空间进行初始化,而 new
如:

int main()
{
	//对一个变量初始化
	int* p = new int(10);	//在后面加括号再加初始化的值

	//对数组进行初始化
	int* pp = new int[5] {1, 2, 3, 4, 5};	//在后面加花括号再加初始化的值

	cout << *p << endl;

	for (int i = 0; i < 5; i++)
	{
		cout << pp[i] << " ";
	}

	return 0;
}

在这里插入图片描述

4、对于自定义类型,new能调用其构造函数,delete能调用其析构函数,而malloc/free不行。

如:

class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
};

int main()
{
	//用malloc申请
	A* a = (A*)malloc(sizeof(A));
	free(a);

	cout << "划分线" << endl;

	//用new申请一个自定义类型空间
	A* p = new A;

	//用new申请一个自定义类型数组
	A* pp = new A[10];

	//释放
	delete p;
	delete[]pp;

	return 0;
}

在这里插入图片描述

5、在申请空间失败时malloc会返回NULL,而new则会抛出异常。

四、new/delete 的实现原理

operator new 函数(底层还是使用malloc申请空间)是 new 的底层实现。
operator delete 函数(底层还是使用free释放空间)是 delete 的底层实现。
operator new[] 函数是 new 类型[ ]的实现。
operator delete[] 函数是 delete[] 的实现。

对于内置类型

如果申请的是内置类型的空间,newmallocdeletefree基本类似,不同的地方是:
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来释空间。

练习1
使用 char* p = new char[100]申请一段内存,然后使用delete p释放,有什么问题?( )
A.会有内存泄露
B.不会有内存泄露,但不建议用
C.编译就会报错,必须使用delete []p
D.编译没问题,运行会直接崩溃
答案:B

A.对于内置类型,此时delete就相当于free,因此不会造成内存泄漏
B.正确
C.编译不会报错,建议针对数组释放使用delete[],如果是自定义类型,不使用方括号就会运行时错误
D.对于内置类型,程序不会崩溃,但不建议这样使用

练习2
ClassA *pclassa=new ClassA[5];delete pclassa;c++语言中,类ClassA的构造函数和析构函数的执行次数分别为( )
A.5,1
B.1,1
C.5,5
D.程序可能崩溃
答案:D

A.申请对象数组,会调用构造函数5次,delete由于没有使用[],此时只会调用一次析构函数,但往往会引发程序崩溃
B.构造函数会调用5次
C.析构函数此时只会调用1次,要想完整释放数组空间,需要使用[]
D.正确

五、匹配问题

关于malloc/free 和 new/delete 申请和释放匹配

1、对于内置类型,是可以的,但是不建议,最好还是配对使用

//内置类型
int main()
{	
	//new 申请
	int* p = new int;

	//free 释放
	free(p);

	//malloc 申请
	int* pp = (int*)malloc(sizeof(int));

	//delete 释放
	delete pp;

	return 0;
}

会报警告:
在这里插入图片描述
在这里插入图片描述

2、对于自定义类型来说很容易出现问题,如下面

(1)申请数组

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

int main()
{
	cout << sizeof(A) << endl;	//大小为 4
	
	// 用 malloc 申请 申请空间的大小为 80字节
	A* pp = (A*)malloc(sizeof(A) * 20);

	//用 new  申请  申请的空间大小为 88字节(原本是应为 80 字节,但是多出来的8字节为保存申请多少个A )
	A* p = new A[20];	

	//用 free 释放
	free(p);	//直接崩掉,因为p的地址为申请的88个字节中的第8个字节地址,所以有8字节无法释放并且无法调用析构
	//用delete 释放
	delete [] pp;	//因为不知道应该析构多少个A(用new会保存申请了多少个A,这时delete就会知道)
	// ,所以出现死循环析构

	return 0;
}

new A[20] 申请需要的字节
在这里插入图片描述
在这里插入图片描述

malloc(sizeof(A) * 20) 申请需要的字节

在这里插入图片描述

(2)申请一个自定义类型

//申请一个自定义类型
// 用 malloc 申请 申请空间的大小为 4字节  
A* pp = (A*)malloc(sizeof(A));	//少了构造

//用delete释放  
delete pp;	//可以但是不建议

用 new  申请  申请的空间大小为 4 字节
A* p = new A;	

free(p);	//不会报错,少了析构,当自定义类型里有需要释放的资源是就会出现内存泄漏

(3)总结:
尽量不要用这种不配对的情况,不然可能会出现各种各样的问题,最好配对使用,这样才能保证程序不会在这方面出错。

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

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

相关文章

Paddle 1.8 与 Paddle 2.0 API 映射表

安装2.6的paddlepaddle之后总是报fluid的错误&#xff0c;查询得知这个接口已经弃用了&#xff0c;但是一直找不到替换接口&#xff0c;偶然查询报错信息的时候找到了映射表&#xff0c;转存一下。 Paddle 1.8 与 Paddle 2.0 API 映射表

打开IIS网站网页错误提示Argument ‘Key must not be null‘ cannot be null.解决方案 Oracle数据库监听

打开网页异常如下&#xff1a; /“应用程序中的服务器错误。 Argument Key must not be null cannot be null.参数名:Key must not be null 客户端 连接oracle 提示&#xff1a;ORA-12541:TNS:无监听程序 按组合键WindowsR&#xff0c;打开运行 输入命令&#xff1a;lsnrctl s…

道一云与畅捷通T+对接集成获取报销信息列表连通凭证创建(报销差旅费(天水))

道一云与畅捷通T对接集成获取报销信息列表连通凭证创建(报销差旅费&#xff08;天水&#xff09;) 对接源平台:道一云 在道一云坚实的技术基础上&#xff0c;道一云推出全新升级的2.0产品矩阵&#xff0c;分别是低码平台、智能门户、场景应用。基于云原生底座&#xff0c;为企业…

解决DataGrip连接MySQL8时出现时区错误问题

解决办法&#xff1a;在url后面拼接时区参数 ?serverTimezoneAsia/Shanghai

虚拟仿真实训室+实时云渲染,便捷高效的教学新体验

一、VR虚拟仿真实训室的优势和缺点 信息技术的发展在教育方面的应用也逐渐广泛起来&#xff0c;一种新兴的教学手段正以其独特的魅力打破传统教育的壁垒——这就是虚拟仿真教学。一些高校中会建立vr仿真实训室来供学生进行学习。这种形式有哪些优势和缺点呢&#xff1f; 优势…

手撕sql面试题:计算出在校人数,字段中含有学生的学制

今天分享一道面试题!如下&#xff1a; 有一个录取学生人数表&#xff0c;记录的是每年录取学生人数和入学学生的学制 以下是表结构&#xff1a; CREATE TABLE admit ( id int(11) NOT NULL AUTO_INCREMENT, year int(255) DEFAULT NULL COMMENT 入学年度, num int(255) …

前端css中filter(滤镜)的使用

前端css中filter的使用 一、前言二、补充内容说明三、模糊&#xff08;一&#xff09;、模糊效果&#xff0c;源码1&#xff08;二&#xff09;、源码1运行效果1.视频演示2.截图演示 四、阴影&#xff08;一&#xff09;、阴影效果&#xff0c;源码2&#xff08;二&#xff09;…

后端-MySQL-week11 事务

事务 简介 操作 有两种方式&#xff0c;一种是设置为手动提交——不执行“commit”不进行变更&#xff1b;另一种是手动开启一个事务&#xff0c;用开启事务的代码&#xff08;SQL语句&#xff09;来创建一个需要“commit”才能进行变更的事务 1.第一种方式 2.第二种方式 四…

C++ | Leetcode C++题解之第46题全排列

题目&#xff1a; 题解&#xff1a; class Solution { public:void backtrack(vector<vector<int>>& res, vector<int>& output, int first, int len){// 所有数都填完了if (first len) {res.emplace_back(output);return;}for (int i first; i &…

如何使用 Vercel 托管静态网站

今天向大家介绍 Vercel 托管静态网站的几种方式&#xff0c;不熟悉 Vercel 的伙伴可以看一下之前的文章&#xff1a;Vercel: 开发者免费的网站托管平台 Github 部署 打开 Vercel 登录界面&#xff0c;推荐使用 GitHub账号 授权登录。 来到控制台界面&#xff0c;点击 Add New …

Docker 命令 镜像操作 容器操作 备份与迁移 DockerFile

什么是Docker&#xff1f; Docker是一种开源应用容器引擎&#xff0c;开发者可以打包自己的应 用以及依赖包到可移植的容器中&#xff0c;然后发布到任何linux机器上。 Docker客居在操作系统内核上的用户空间&#xff0c;只能运行与底层宿主 机相同的操作系统之上。主要目标是…

线性代数-知识点复习(面试用)

整理&#xff1a;Peter1146717850 一、向量与线性组合 向量&#xff1a;往什么方向走多么远 e.g. ( 1 2 ) \begin{pmatrix} 1 \\ 2\end{pmatrix} (12​) 向量的模&#xff1a;向量的长度 向量的加减法&#xff1a;向量对应元素相加减&#xff08;前提&#xff1a;维度相同…

免费SSL证书和付费SSL证书区别在哪

免费SSL证书与付费SSL证书在多个方面存在差异&#xff0c;这些差异主要体现在认证级别、保障金额以及服务范围上。在以下几个方面存在显著区别&#xff1a; 1、验证类型和信任级别&#xff1a; 免费SSL证书&#xff1a;通常只提供域名验证&#xff08;DV&#xff09;级别的证…

【Linux】日志分析与管理

作为一个运维&#xff0c;如果不会看日志&#xff0c;就好比是冬天刚刚用热水泡完了脚&#xff0c;接着就立马让人把水喝掉。 目录 一、Inode介绍 1.1 什么是inode 1.2 inode表内容 1.3 查看inode号的方式 二、日志分析 2.1 日志的用途 2.2 日志的分类 2.3 日志级别 2…

电力调度自动化系统由什么构成?

电力调度自动化系统由什么构成&#xff1f; 电力调度自动化系统通过数据采集与传输、数据处理与存储、监视与控制、优化与决策、通信网络和系统应用软件等构成&#xff0c;实现对电力系统的监控、控制和优化。 电力调度自动化系统是一种集成了计算机技术、通信技术、自动化技术…

从阿里云OSS迁移到AWS S3的步骤

随着企业数字化转型的加速,云计算成为企业IT基础设施不可或缺的部分。对象存储作为云计算的重要组成部分,为企业提供了可靠、安全、低成本的数据存储和管理解决方案。在选择对象存储服务时,企业需要根据自身需求和发展战略来进行全面评估。我们九河云&#xff0c;获得AWS官方认…

vue3 修改路由中的meta属性

有些时候可能需要在路由跳转前后修改meta里面的相关属性值&#xff0c;这个时候就需要使用钩子函数&#xff08;路由守卫&#xff09;&#xff0c;钩子函数有全局钩子&#xff0c;局部组件钩子函数以及路由配置里面的钩子函数 &#xff08;这些也叫路由守卫&#xff09; 1.全局…

Windows 10 安装配置WSL2(Ubuntu 20.04)教程

Windows 10 安装配置WSL2&#xff08;Ubuntu 20.04&#xff09;教程 一、WSL简介 WSL&#xff08;Windows Subsystem for Linux&#xff09;是一个兼容层&#xff0c;允许在Windows 10上原生运行Linux二进制可执行文件。 二、安装WSL2 3.1 传统手动安装 更新系统&#xff…

“亚马逊依赖”之下,傲基科技的品牌势能如何提升?

受益于出口政策红利、低人工成本、完善的供应链以及成熟的生产工艺优势&#xff0c;近年来我国家具出口行业迅速发展。 数据显示&#xff0c;我国家具出口规模1995年仅为11.06亿美元&#xff0c;至2023年增至641.96亿美元。随着出口规模持续扩大&#xff0c;相关企业积极走入公…

问题速查手册(时实更新)【Ctrl+F】输入关键词可快速查询

1.1.虚拟机和机器人上树莓派的密码是多少 虚拟机和小车的账号和密码都是nanorobot&#xff0c;在linux下输入密码无任何提示&#xff0c;退格键也没有用。输错请按回车后重新输入。 注&#xff1a;2021年四月份以后购买的机器人账号和密码已更改为bingda 1.2.请严格区分PC端…