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.mzph.cn/bicheng/1475.shtml

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

相关文章

PyTorch与深度学习:探索现代神经网络的魅力

在科技飞速发展的今天&#xff0c;深度学习作为人工智能领域的重要分支&#xff0c;已经在图像识别、自然语言处理、语音识别等多个领域取得了突破性的进展。而PyTorch&#xff0c;作为一款开源的深度学习框架&#xff0c;以其简洁易用、动态计算图等特性&#xff0c;赢得了广大…

2024年3月青少年软件编程(Python) 等级考试试卷(一级)

2024.3 青少年软件编程&#xff08;Python&#xff09; 等级考试试卷&#xff08;一级&#xff09; 一、 单选题(共 25 题&#xff0c; 共 50 分) 1.下列哪个命令&#xff0c; 可以将 2024 转换成 2024 呢&#xff1f; &#xff08; &#xff09; A.str(2024) B.int(2024) C.fl…

Django中间件的源码解析流程(上)——中间件载入的前置

目录 1. ​前言​ 2. 请求的入口 3. 中间件加载的入口 4. 源码中的闭包实现 5. 最后 1. 前言 哈喽&#xff0c;大家好&#xff0c;我是小K,今天咋们分享的内容是&#xff1a;在学会Django中间件之后&#xff0c; 我们继续深入底层源码。 在执行中间件时请求到来总是从前往后…

ChatGPT研究论文提示词集合3-【数据收集】、【数据分析】和【解释与讨论】

点击下方▼▼▼▼链接直达AIPaperPass &#xff01; AIPaperPass - AI论文写作指导平台 目录 1.数据收集 2.数据分析 3.讨论与解释 4.书籍介绍 AIPaperPass智能论文写作平台 近期小编按照学术论文的流程&#xff0c;精心准备一套学术研究各个流程的提示词集合。总共14个步…

【IDEA】用idea导入eclipse的项目后,提示:The file was loaded in a wrong encoding ‘utf-8‘

前言 最近用IDEA导入一个exlipse项目后&#xff0c;窗口出现这个红色提示&#xff1a; 可以项目中的中文&#xff0c;包括注释都是乱码&#xff0c;要解决问题就跟我开始做吧。 一定要看仔细在操作&#xff01; 一定要看仔细在操作&#xff01; 一定要看仔细在操作&#xf…

for循环的用法

for循环的用法 for 循环是一种在 Python 中用于迭代序列&#xff08;如列表、元组或字符串&#xff09;或其他可迭代对象的循环结构。下面是一些常见的 for 循环用法&#xff1a; 遍历列表&#xff1a;使用 for 循环遍历列表中的元素。 fruits ["apple", "b…

rmallox勒索病毒威胁网络安全:如何避免数据被锁定

尊敬的读者&#xff1a; 随着信息技术的飞速发展&#xff0c;网络空间的安全问题日益凸显。近年来&#xff0c;一种名为.rmallox的勒索病毒频繁出没&#xff0c;给广大计算机用户带来了严重的困扰。本文将对该病毒进行深入剖析&#xff0c;并探讨相应的应对策略。在面对被勒索…

飞书API(5):查看多维表 28 种数据类型的数据结构

一、引入 前面我们用于测试的数据集其实都是比较常用的数据&#xff0c;比如说文本、数字、单选等&#xff0c;但飞书多维表并不仅仅只有这些数据&#xff0c;截止发文&#xff0c;飞书多维表应用上支持28种数据类型&#xff0c;在数据层面飞书官方只提供了23种数据类型&#…

微信小程序vue.js+uniapp服装商城销售管理系统nodejs-java

本技术是java平台的开源应用框架&#xff0c;其目的是简化Sping的初始搭建和开发过程。默认配置了很多框架的使用方式&#xff0c;自动加载Jar包&#xff0c;为了让用户尽可能快的跑起来spring应用程序。 SpinrgBoot的主要优点有&#xff1a; 1、为所有spring开发提供了一个更快…

MySQL数据库——17.正则表达式

MySQL正则表达式是一种强大的模式匹配工具,用于在文本数据中搜索和匹配特定的模式。MySQL使用正则表达式来执行模式匹配的操作,可以在SELECT语句的WHERE子句中使用,也可以在其他SQL语句中使用。 基本语法: 在MySQL中,正则表达式通常与REGEXP关键字一起使用。基本语法如下…

AI 智能工具以及热门AI开源项目整理,包含国内中科院版GPT

AI 智能工具以及热门AI开源项目整理&#xff0c;包含国内中科院版GPT。 不用xx即可访问的镜像网站 https://chat1.yqcloud.top https://chat.bnu120.space https://chat.aidutu.cn https://hzdjs.cn/chatgpt https://chats.fenqubiao.com/zh 需要xx才能访问的网站 https://o…

云原生小疑问 ⁉️ - Kubernetes 下重启容器会丢失数据吗?

文章目录 问题哪些数据需要持久化&#xff1f;解决办法参考 问题 在 docker 环境下&#xff0c;容器重启后还是原来的容器&#xff0c;数据并没有丢失。那是不是 k8s 环境下&#xff0c;重启也不会丢失呢&#xff1f; 在kubernetes/RainBond环境下&#xff0c;最小化的管理单元…

Vue模版语法(初学Vue之v-指令语法)

目录 一、介绍 1.概念 2.常见指令语法及用法 1.v-bind: 2.v-model: 3.v-if / v-else-if / v-else: 4.v-for: 5.v-on: 6.v-show: 7.v-pre: 8.v-cloak: 二、使用 1.Mustache插值语法 2.v-once指令使用 3.v-text指令使用 4.v-html指令使用 5.v-pre指令使用 6.v-…

「 网络安全常用术语解读 」什么是0day、1day、nday漏洞

1. 引言 漏洞攻击的时间窗口被称为漏洞窗口&#xff08;window of vulnerability&#xff09;。一般来说&#xff0c;漏洞窗口持续的时间越长&#xff0c;攻击者可以利用漏洞进行攻击的可能性就越大。 2. 0day 漏洞 0day 漏洞&#xff0c;又被称为"零日漏洞"&…

Ocelot扩展应用

Ocelot 是一个灵活且可扩展的 API 网关框架&#xff0c;它可以在各种应用场景中扩展和定制。通过扩展 Ocelot&#xff0c;你可以在网关中添加各种自定义功能、集成第三方服务以及优化性能。以下是一些 Ocelot 扩展应用的示例&#xff1a; 1. 自定义中间件&#xff1a; Ocelot…

react之组件与JSX

第一章 - 描述用户界面 概述&#xff1a;React是一个用于构建用户界面&#xff08;UI&#xff09;的JavaScript库&#xff0c;用户界面由按钮&#xff0c;文本和图像等小单元内容构建而成。React帮助你把它们组合成可重用&#xff0c;可嵌套的组件。从web端网站到移动端应用&a…

[Java基础面试题] volatie 与 synchronized

1. 说一下 volatie 在Java中&#xff0c;volatile 关键字用于修饰变量&#xff0c;表示该变量是易变的&#xff0c;其值可能会被不同的线程修改。使用volatile关键字声明的变量具有两个特性&#xff1a; 原子性&#xff1a;volatile 变量的读写操作都是原子性的&#xff0c;即…

【讲解下Spring Boot单元测试】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

docker 容器数据在盘与盘之间迁移

docker 容器数据在盘与盘之间迁移 1、停止容器systemctl stop docker2、docker目录备份# 备份 切记一定要先备份&#xff0c; /var/lib/docker目录为原docker数据目录&#xff0c; /data/docker_data_bak 为新盘的备份目录 cp -r /var/lib/docker /data/docker_data_bak # 移动…

记录mac上图像处理

自适应二值化 import cv2# 读取图像 image cv2.imread(/Users/sinkarsenic/Downloads/用所选项目新建的文件夹/2.jpg, 0) # 使用灰度模式读取图像# 自适应二值化 adaptive_thresh cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 31, 2…