首页 > 系统相关 >【C++】内存管理

【C++】内存管理

时间:2024-06-01 17:33:21浏览次数:26  
标签:malloc 管理 int C++ 空间 内存 operator new delete

文章目录

在这里插入图片描述

1.回顾C/C++的内存管理

首先,我们来回顾一下内存中的区域划分,做一下下面的题目吧:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

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

void Test2()
{
	// malloc/calloc/realloc的区别是什么?
	//1.malloc只开空间
	//2.calloc开空间,且会初始化
	//3.realloc是扩容,原地扩/异地扩,
	int* p1 = (int*)malloc(sizeof(int));
	free(p1);
	int* p2 = (int*)calloc(4, sizeof(int));
	int* p3 = (int*)realloc(p2, sizeof(int) * 10);
	// 这里需要free(p2)吗?
	//不需要,realloc扩容时会释放原来的空间
	free(p3);
}

2. C++内存管理方式

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

2.1 new/delete对于内置类型

对内置类型那个来说,new/delete 与malloc()/free()没有区别。

new:对于内置类型来说,默认不初始化,但可以初始化

在这里插入图片描述

注意:

  • 申请和释放单个元素的空间,使用new和delete操作符,
  • 申请和释放连续的空间,使用new[ ]和delete[ ]
  • 尽量匹配起来使用。
int main()
{
	//动态申请一个int空间
	int* a = new int;
	//动态申请一个int空间,并初始化为10
	int* b = new int(10);
	//动态申请一个10个整型的数组
	int* parr1 = new int[10];
	//动态申请一个10个整型的数组,并初始化
	int* parr2 = new int[10]{ 1,2,3,4,5 };

	delete a;
	delete b;
	delete[] parr1;
	delete[] parr2;
	return 0;
}

2.2 new/delete对于自定义

new/delete 和 malloc/free最大区别是: new/delete对于自定义类型除了开空间还会调用其构造函数和析构函数。

在这里插入图片描述

自动调用构造和析构

在这里插入图片描述

2.3 operator new与operator delete函数

new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数。

  • new在底层调用operator new全局函数来申请空间,new其实就是operator new(malloc) + 构造函数
  • delete在底层通过operator delete全局函数来释放空间,delete其实就是析构函数+operator delete(free)

operator new:该函数实际通过malloc来申请空间

void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
	// try to allocate size bytes
	void* p;
	while ((p = malloc(size)) == 0) //调用malloc申请空间
		if (_callnewh(size) == 0)
		{
			// report no memory
			// 如果申请内存失败了,这里会抛出bad_alloc 类型异常
			static const std::bad_alloc nomem;
			_RAISE(nomem);
		}
	return (p);
}
  • 当malloc申请空间成功时直接返回
  • 申请空间失败,尝试执行空间不足应对措施,如果该应对措施用户设置了,则继续申请,否则抛异常;而malloc申请失败就只会有一个返回码,这就是malloc与operator new的区别。

我们可以观察一下它的汇编代码:
在这里插入图片描述

注意:
operator new 和operatordelete 与构造函数和析构函数处理的不是同一块空间。
在这里插入图片描述

2.4 new和delete的实现原理

  1. 内置类型

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

  1. 自定义类型
  • new的原理

    • 调用operator new函数申请空间
    • 在申请的空间上执行构造函数,完成对象的构造
  • delete的原理

    • 在空间上执行析构函数,完成对象中资源的清理工作
    • . 调用operator delete函数释放对象的空间
  • new T[N]的原理

    • 调用operator new[]函数,在operator new[ ]中实际调用operator new函数完成N个对象空间的申请
    • 在申请的空间上执行N次构造函数
  • delete[ ]的原理

    • 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
    • 调用operator delete[ ]释放空间,实际在operator delete[ ]中调用operator delete来释放空间

2.5 定位new表达式

如果我们不让你使用new和delete,那么我们怎么管理对象的内存呢?
在这里插入图片描述

但是这样写又调用不了构造。
怎么办呢?

定位new表达式 是在已分配的原始内存空间中调用构造函数初始化一个对象。

使用格式:
new (place_address) type或者new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表

在这里插入图片描述

3. 常见面试题

一、 malloc/free和new/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需要捕获异常
  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数;而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

标签:malloc,管理,int,C++,空间,内存,operator,new,delete
From: https://blog.csdn.net/weixin_69380220/article/details/139362263

相关文章

  • 【C/C++】--- 指针详解 2.0
    接下来进入指针的进阶部分,准备好大脑补充:(重点)数组名是数组首元素地址数组首元素地址和数组地址,值相同,但本质不同,区别在于二者的类型不相同比如数组intarr[10];数组首元素地址的类型:首先这是一个地址所以要用指针接收,(),然后是地址指向元素的类型为int,所以这个指针的......
  • macOS下使用bits/stdc++.h万能头文件
     macOS下使用bits/stdc++.h万能头文件1.终端中输入echo|g++-v-xc++-E-#include<...>searchstartshere:/usr/local/include/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/Library/Developer/CommandLineTools/usr/lib/clang/12.......
  • C++——类
    目录C++类访问权限虚函数1.定义底层实现2.构造函数/析构函数3.抽象类/纯虚函数常见问题1.虚函数不可以声明为inline吗2.构造函数为什么不能为虚函数?3.析构函数为什么可以为虚函数?4.构造函数和析构函数可以调用虚函数吗?5.虚析构函数的作用,父类的析构函数是否要设置为虚......
  • 使用SpringBoot对Brc20 Ordinals铭文诊断管理系统全开源
    ......
  • vue3 状态管理库pinia使用测试
    Home.vue组件中使用测试<template><divclass="home"><div>fone:{{fone}}</div><div>ftwo:{{ftwo}}</div><div>ffour:{{ffour}}</div><div&g......
  • C语言学生成绩管理系统
    部分源码//Anhighlightedblock#include<stdio.h>#include<stdlib.h>#include<string.h>#defineMAX_STUDENTS1000typedefstruct{charid[......
  • 宝塔Linux面板-Docker管理(2024详解)
    上一篇文章《宝塔Linux可视化运维面板-详细教程2024》,详细介绍了宝塔Linux面板的详细安装和配置方法。本文详细介绍使用Linux面板管理服务器Docker环境。目录1、安装Docker1.1在线安装​编辑 1.2手动安装1.3运行状态1.4镜像加速2应用商店 3总览 4容器4.1......
  • 权限管理,鸿蒙Next版
      一、应用权限概述注意事项在鸿蒙开发中,调用部分API时需要申请权限后,才能调用,如:网络请求,获取网络信息等。部分API权限调用的时候还会弹窗,如:麦克风、位置、摄像头、相册、传感器(sensor)、日历等。申请应用权限时,需要注意两个关键信息:权限级别授权方式权限文档截图......
  • C语言文件操作指南:读写与管理
    在C语言编程中,文件操作是一个重要的主题。无论是读取配置文件、记录日志,还是处理大量数据,文件操作都是必不可少的。本文将介绍C语言中文件操作的基本概念和常用方法,帮助你轻松掌握这项技能。一、文件操作的基本概念在C语言中,文件操作主要包括以下几步:打开文件:创建一个文件指......
  • 基于SpringBoot+Vue的在线答疑管理系统设计与实现毕设(文档+源码)
            目录一、项目介绍二、开发环境三、功能介绍四、核心代码五、效果图六、源码获取:        大家好呀,我是一个混迹在java圈的码农。今天要和大家分享的是一款基于SpringBoot+Vue的在线答疑管理系统,项目源码请点击文章末尾联系我哦~目前有各类成......