【C++】---内存管理new和delete详解

在这里插入图片描述

一、C/C++内存分布

C/C++内存被分为6个区域:
(1) 内核空间:存放内核代码和环境变量。

(2)栈区:向下增长存放非静态局部变量,函数参数,返回值等等

(3)内存映射段:文件映射,匿名映射,动态库。

(4)堆区:向上增长用于程序运行时动态内存的分配

(5)数据段:也叫,静态区/全局域,(存放全局变量和静态变量

(6)代码段:也叫常量区(存放可读代码和只读常量)

在这里插入图片描述
看看下面代码的例题:

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在哪里?____ staticGlobalVar在哪里?____
    staticVar在哪里?____ localVar在哪里?____
    num1 在哪里?____

    char2在哪里?____ *char2在哪里?___
    pChar3在哪里?____ *pChar3在哪里?____
    ptr1在哪里?____ *ptr1在哪里?____

  2. 填空题:
    sizeof(num1) = ____;
    sizeof(char2) = ____; strlen(char2) = ____;
    sizeof(pChar3) = ____; strlen(pChar3) = ____;
    sizeof(ptr1) = ____;

    1. sizeof 和 strlen 区别?

1.C C C A A
2. A A A D A B
3.40 5 4 4或8 4 4或8

3.sizeof和strlen的区别:
(1)char ch2[ ]=“abcd”; // sizeof(ch2)=5 (因为末尾还有一个’\0’)
// strlen(ch2)=4 (因为strlen其他都不管,遇到’\0’就结束,‘\0’不计入
(2)sizeof()内部要看变量是否为指针,若是指针==4/8
strlen不看变量是否为指针,只看’\0’ ,遇到’\0’结束为止!!!

4.对char2,pchar3,ptr1的解释:
(1)字符串存在于常量区,当拿来初始化char2的时候,char2会在栈区开辟一个空间,然后再把字符串拷贝给char2,char2就在栈区。

(2)char2是数组名,对地址解引用,*char2仍然在栈区!

(3) 被const的修饰变量不一定在常量区,有可能const修饰的是常变量,存放在栈区!

(4)pchar3是在栈上的指针变量,*pchar3=='‘abcd\0’'是:指向的字符串“abcd\0”存放在常量区

(5)ptr1是在栈上的指针变量,ptr1由于是由malloc出来的,所以ptr1指向的空间(即:*ptr1)在堆区

在这里插入图片描述

二、C/C++使用new和delete的原因

new和delete是C++向内存申请空间和释放空间的操作符, C++为什么要使用new和delete?

1.C语言使用malloc、calloc、realloc、free管理的不便之处在于:

(1)需要手动申请空间,手动计算申请的字节大小。

(2)对返回值void*需要进行强转,否则无法进行解引用。

(3)内存申请是否成功还需要进行判断。

(4)需要include头文件<stdlib.h>

2.new和delete对自定义类型也会进行处理:

(1)new会调用构造函数对类对象进行初始化

(2)delete会调用析构函数进行资源清理

三、C++动态管理内存的方式

1.new和delete

(1)new/delete和malloc/free对内置类型的操作没有区别
注意:
①申请和释放单个空间,需要用new和delete。
②申请和释放多个空间,需要用new [ ]和delete [ ]

(2)new的特点:

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;int main()
{// 1.C语言申请空间int* p0 = (int*)malloc(sizeof(int) * 4);if (p0 == NULL){perror("malloc fail");return 1;}free(p0);// 2.new 1个int整型的元素int* p1 = new int;delete p1;// 3.new 10个int整型元素,(即:数组)int* p2 = new int[10];// 申请的时候为:new[ ] ,释放的时候,必须要用delete[ ] delete[] p2;// 4.可以控制初始化int* p3 = new int(10); // new一个int整型 并且初始化为10delete p3;// 5.new失败后会抛异常,不必手动检查
}

C++11开始支持new初始化数组:
如果没有初始化到的,默认为0

int* p4 = new int[10] {1, 2, 3, 4, 5};
delete[] p4;

在这里插入图片描述
(3)new/delete和malloc/free对自定义类型的操作有区别:

①malloc/free对自定义类型的操作只会开空间/释放空间

②new操作自定义类型会开空间+构造函数初始化,delete操作自定义类型会调用析构函数清理+释放空间

class ListNode
{
public:ListNode* _prev;ListNode* _next;int _val ;ListNode():_prev(nullptr),_next(nullptr),_val(0){cout << "this _val=" << _val << endl;}~ListNode(){cout << "~ListNode()" << endl;}
};int main()
{ListNode* p1 = (ListNode*)malloc(sizeof(ListNode) * 4);ListNode* p2 = new ListNode;free(p1);delete(p2);return 0;
}

在这里插入图片描述
当程序走完第94行之后,那么p2里面的值都被初始化了。然而对于93行malloc出来的值都是随机值。从调试的界面可以看出,它也调用了构造函数,所以打印出:this _val=0

这就是new和malloc的区别,new对自定义类型会调用构造函数(delete会调用析构函数),对对象进行初始化和空间清理,而C语言之前的malloc和free不会这样做,他们只会开辟空间和释放空间。

2.operator new和operator delete

(1)定义operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,(operator new是对malloc的封装),delete在底层通过operator delete全局函数来释放空间,(operator delete是对free的封装)它们不是new和delete的重载。
(2)与malloc区别:operator new、operator delete的用法和malloc、free的用法是一样的,功能都是在堆上申请释放空间,但是失败了的处理方式不一样,malloc失败返回NULL,operator new失败以后抛异常。
使用new为自定义类型ListNode申请空间并初始化:new会调用operator new函数和构造函数,operator new会调用malloc和失败抛异常机制,因此new和operator new申请失败都会抛异常:
在这里插入图片描述
从上图可以看出,new并不直接调用 malloc,而是调用了operator new,因为operator new被封装了,malloc申请失败直接报返回值,但operator new申请失败会抛异常

在这里插入图片描述
总结:
对于自定义类型来说:(只有自定义类型才有构造和析构,内置类型不存在的)
(1)new—>operator new<—>malloc+构造函数
(2)delete—>析构函数+operator delete<—>free 注意两者的顺序不同

3.总结

malloc/free和new/delete总结:
(1)malloc/free是函数,new/delete是操作符

(2)malloc申请的空间不会初始化,new可以初始化

(3)malloc申请的空间需要手动计算并传递过去,而new只需要在后面跟上空间类型即可。

(4)new不需要强转,而malloc需要

(5)malloc申请空间之后需要判断是否申请失败,new不需要,但是new需要捕获异常

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

五、内存泄漏

1.定义:内存泄漏的概念:一块已经不用的空间,没有释放

2.危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会 导致响应越来越慢,最终卡死。

3.有关内存泄漏的例题

class A
{
public:A(){cout << "A()" << endl;}~A(){cout << "~A()" << endl;}
};int main()
{A* a = new A[5];//delete a;  内存泄漏,只释放了1次delete[] a;return 0;
}

关键点:(记住:一定要匹配使用,如若违背结果将不确定!)

new—>delete
new[ ] —>delete[ ]
在这里插入图片描述


好了,今天的分享就到这里了
如果对你有帮助,记得点赞👍+关注哦!
我的主页还有其他文章,欢迎学习指点。关注我,让我们一起学习,一起成长吧!
在这里插入图片描述

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

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

相关文章

理解npm run dev 和 npm run serve的区别

文章目录 1. 分析npm run2. dev与serve的区别 1. 分析npm run npm npm 是 Node.js 的包管理器&#xff0c;它允许你安装、更新、删除和管理 Node.js 的模块和应用程序。 run run 是 npm 的一个子命令&#xff0c;用于执行在 package.json 文件的 scripts 部分定义的脚本。 dev…

C#中字典Dictionary的实现原理

在 C# 中&#xff0c;字典的实现通常使用哈希表。Dictionary<TKey, TValue> 类就是 C# 中的哈希表实现之一。 哈希表的数据结构&#xff1a; Dictionary<TKey, TValue> 内部使用了哈希表的数据结构来存储键值对。哈希表通常是一个数组&#xff0c;每个数组元素通常…

导入arviz出现的错误

导入arviz时&#xff0c;很有可能出现 UnicodeDecodeError: ‘gbk’ codec can’t decode byte 0xba in position 2367: illegal multibyte sequence 这是因为我们的操作系统环境引起的。通过仔细阅读错误信息&#xff0c;可以定位出是pathlib.py中的read_text不传encoding参数…

OSI参考模型和TCP/IP网络参考模型

1、OSI参考模型 1.1 产生背景 为了解决网络之间的兼容性问题,实现网络设备间的相互通讯,国际标准化组织ISO于1984年提出了OSIRM(Open System Interconnection Reference Model,开放系统互连参考模型)。OSI参考模型很快成为计算机网络通信的基础模型。由于种种原因,并没有…

第二证券:买什么股比较安全?买股小技巧!

股票与基金、银行存款相比较&#xff0c;其危险性较高&#xff0c;不同类型的个股&#xff0c;其危险性有所不同&#xff0c;其中购买以下类型的个股&#xff0c;安全性相对来说要高一点&#xff1a; 1、权重股 权重股与中小盘股相比较&#xff0c;其流通盘较大&#xff0c;涨…

加购与心愿单:提升亚马逊产品排名的双重利器

作为亚马逊卖家&#xff0c;我一直在寻找提升产品排名和销量的方法。最近&#xff0c;我尝试了使用亚马逊鲲鹏系统来优化关键词排名和增加转化率&#xff0c;我想分享一下我的使用体验和反馈。 首先&#xff0c;我深入了解了亚马逊关键词排名的原理&#xff0c;意识到通过加购可…

【分享】WinRAR解压缩软件的3个密码功能

WinRAR是一款功能强大的解压缩软件&#xff0c;除了用来解压缩文件&#xff0c;还可以作为加密软件&#xff0c;给压缩包设置密码&#xff0c;达到保护文件的目的。今天来分享一下WinRAR的3个密码功能&#xff0c;一起来看看吧&#xff01; 功能一&#xff1a;设置“打开密码”…

WPF 附加属性+控件模板,完成自定义控件。建议观看HandyControl源码

文章目录 相关连接前言需要实现的效果附加属性添加附加属性&#xff0c;以Test修改FontSize为例依赖属性使用触发器使用直接操控 结论 控件模板&#xff0c;在HandyControl的基础上面进行修改参考HandyControl的源码控件模板原型控件模板 控件模板触发器完整样式简单使用 结论 …

SwiftUI中的 WebView

SwiftUI中的WebView是一个用于显示网页内容的视图。它是使用WebKit框架的一个封装。 要在SwiftUI中使用WebView&#xff0c;你可以按照以下步骤操作&#xff1a; 首先&#xff0c;导入WebKit框架&#xff1a; import WebKit创建一个WebView实例&#xff1a; struct WebView…

学习pybind11:Hello World例子

首先要明白pybind11是干啥的&#xff0c;对于一个C/C库&#xff0c;可以用pybind11封装它的接口为Python接口&#xff0c;这样得到一个python库&#xff0c;就可以把功能强大的库丢给使用python的boys & girls使用了~ 因此&#xff0c;使用pybind11做封装&#xff0c;是我…

Stable Diffusion 绘画入门教程(webui)-ControlNet(Shuffle)

Shuffle(随机洗牌)&#xff0c;这个预处理器会把参考图的颜色打乱搅拌到一起&#xff0c;然后重新组合的方式重新生成一张图&#xff0c;可以想象出来这是一个整体风格控制的处理器。 那么问题来了&#xff0c;官方为啥会设计个这样的处理器呢&#xff0c;主要是给懒人用的&am…

ConvNeXt V2:用MAE训练CNN

论文名称&#xff1a;ConvNeXt V2: Co-designing and Scaling ConvNets with Masked Autoencoders 发表时间&#xff1a;CVPR2023 code链接&#xff1a;代码 作者及组织: Sanghyun Woo&#xff0c;Shoubhik Debnath来自KAIST和Meta AI。 前言 ConvNextV2是借助MAE的思想来训练…