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

文章目录

    • 一、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.hqwc.cn/news/636605.html

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

相关文章

Android开发——Fragment

Demo fragment_blank.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_pare…

Fannel和Calico

一 1、路由器下面每一个端口都是一个vlan,隔离了广播包 192.168.1.0和192.168.2.0他们属于不同的vlan,没有三层交换机或者路由器,他们通不了信 不在同一个vlan,也就是子网,包就会走向网关(也就是路由器那里,路由器有路由表。查看目的地192.168.2.0在b口,从b口出去vlan…

Python编程技巧揭秘:深入理解Lambda函数,如何使用匿名函数简化你的代码

文章目录 1. Lambda函数2. 在实际应用中使用Lambda2.1 使用Lambda函数进行列表排序2.2 在高阶函数中使用Lambda 3. Lambda的局限性和注意点 在这篇文章中&#xff0c;将深入探讨Python中的Lambda函数&#xff0c;这是一种强大的编程工具&#xff0c;可以以更简洁、高效的方式编…

Java基于微信小程序的讲座预约系统的研究与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

PCDN与边缘计算的集成解决方案

PCDN与边缘计算的集成解决方案 在数字化时代&#xff0c;内容的快速、安全地传递至用户变得至关重要。无论是媒体、教育还是其他领域&#xff0c;所有这些行业都需要强大的技术支持以保证信息的实时更新和安全传输。PCDN&#xff08;Peer Content Delivery Network&#xff0c…

c++——类和对象(1)构造,析构函数

类的六个默认函数 如果一个类当中没有成员的话&#xff0c;那叫空类&#xff0c;实际上空类有6个编译器默认生成的函数成员 默认成员函数&#xff1a;没有显示实现&#xff0c;编译器生成的成员函数称为默认成员函数 1&#xff0c;构造函数与构析函数 1.1构造函数的概念 构造…

【MATLAB源码-第194期】基于matlab的MB-OFDM仿真,超宽带(UWB)无线传输。对比LS/DFT及其改进算法。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 一、无线通信的基本原理 无线通信是通过空气或其他介质传播电磁波来传输信息的技术。这种通信方式的核心在于电磁波&#xff0c;它能够在没有物理连接的情况下传输数据。无线通信的基本流程包括&#xff1a; 信号的生成&am…

python使用uiautomator2操作真机(oppo a9x)

环境&#xff1a; python3.8.10&#xff0c;oppo a9x(6G,128g)&#xff0c;版本android 11。 之前写过文章&#xff1a; python使用uiautomator2操作真机&#xff08;荣耀10青春版&#xff09;_python uiautomator2 控制真机-CSDN博客 python使用uiautomator2操作真机&…

c语言之字符串的集合存放形式

采用指针分配的二维数组与直接定义的二维数组&#xff0c;sizeof的不同 采用指针分配的二维数组&#xff1a; 它的遍历方式是&#xff1a; 上面这个是分配二级指针的地址&#xff0c;二级指针就是一片可以用来分配一级指针空间的地址&#xff0c;然后指针寻址本来就可以当成数组…

K8s 部署 MySQL 8.0.20 主从复制结构

一、K8s 部署 MySQL 安装规划 组件replicas类型mysql-master1StatefulSetmysql-slave1StatefulSet 使用 k8s 版本为&#xff1a;v1.18.0 。 本次使用 OpenEBS 来作为存储引擎&#xff0c;OpenEBS 是一个开源的、可扩展的存储平台&#xff0c;它提供了一种简单的方式来创建和…

老阳闲聊|怎么在Temu电商平台上赚钱?

随着互联网技术的飞速发展&#xff0c;电商平台如雨后春笋般涌现&#xff0c;其中Temu电商平台以其独特的商业模式和广阔的市场前景&#xff0c;吸引了众多创业者和商家的目光。那么&#xff0c;如何在Temu电商平台上赚钱呢?本文将为您详细解析。 首先&#xff0c;了解Temu电商…

(2022级)成都工业学院数据库原理及应用实验七: 数据库安全

写在前面 1、基于2022级软件工程/计算机科学与技术实验指导书 2、成品仅提供参考 3、如果成品不满足你的要求&#xff0c;请寻求其他的途径 运行环境 window11家庭版 Navicat Premium 16 Mysql 8.0.36 实验要求 1、创建数据库hospital,在hospital数据库中创建科室表De…