内存管理(c++)

news2024/9/20 18:48:25

欢迎来到本期节目- -

内存区域

c/c++中程序内存区域划分:
在这里插入图片描述
你知道它在内存的哪个区域吗?

int global_var = 1;

static int static_global_var = 1;

void test1()
{
	static int static_part_var = 1;
}
这里的全局变量,静态全局变量,静态局部变量都在数据区。
class Code
{
public:
	void print()	//普通成员函数
	{
		cout << _a << endl;
	}
	static void s_print()	//静态成员函数
	{
		cout << _b << endl;
	}
	
private:
	int _a;		//普通成员变量
	static int _b;	//静态成员变量
};

void test2()
{
	Code obj;
	int part_var;
}
这里的局部变量obj和part_var都在栈中;
但是Code类的静态成员函数和该对象的普通成员函数是在代码区,且Code类的静态成员变量在静态区。
void test3()
{
	char ch1[] = "哈哈";
	const char* ch2 = "哈哈";
}
ch1字符数组的"哈哈"是在栈区上,"哈哈"是被拷贝到栈区的。
*ch2是在常量区。
void test4()
{
	int* ptr = (int*)malloc(sizeof(int));
	*ptr = 1;

	free(ptr);	//养成好习惯——申请的资源要释放
	ptr = nullptr;
}
ptr是一个局部指针变量,所以是在栈区上。
*ptr是在堆区上。

内存管理方式

c管理方式

c管理内存函数有三:

  • malloc

    void* malloc (size_t size);

    该函数会在堆上申请大小为size字节的一段连续空间

    void test1()
    {
    	int* ptr1 = (int*)malloc(sizeof(int));
    	if(ptr1 == nullptr)
    	{
    		perror("malloc");
    		return 1;
    	}
    	//使用空间
    	//释放空间
    	free(ptr1);
    	ptr1 = nullptr;
    }
    

    在这其中,ptr1指向的空间是没有初始化的

  • calloc

    void* calloc (size_t num, size_t size);

    该函数会在堆上申请一段大小为size字节的连续空间,然后初始化

    void test2()
    {
    	int* ptr2 = (int*)calloc(sizeof(int));
    	if(ptr2 == nullptr)
    	{
    		perror("calloc");
    		return 1;
    	}
    	//使用空间
    	//释放空间
    	free(ptr2);
    	ptr2 = nullptr;
    }
    

    在这其中,ptr2指向的空间在开辟之后会初始化为0

  • realloc

    void* realloc (void* ptr, size_t size);

    该函数是为ptr所指向的空间扩容,如果ptr为空,该效果等价与malloc;
    原地扩容;
    异地扩容:扩容会在开好新空间之后,将原数据拷贝到新空间,然后释放旧空间,返回新空间的地址。

    void test2()
    {
    	int* ptr3 = (int*)realloc(nullptr,sizeof(int));
    	if(ptr3 == nullptr)
    	{
    		perror("realloc");
    		return 1;
    	}
    	
    	//扩容
    	int* tmp = (int*)realloc(ptr3,sizeof(int)*10);
    	if(tmp == nullptr)
    	{
    		perror("realloc");
    		free(ptr3);
    		return 1;
    	}
    	else
    	{
    		ptr3 = tmp;
    	}
    	//使用空间
    	//释放空间
    	free(ptr3);
    	ptr3 = nullptr;
    }
    

c++管理方式

new/delete操作符

使用方式:

class my_type
{
public:
	my_type(int n = 0)
	:_n(n)
	{
		cout<<"my_type(int n = 0)"<<endl;
	}
	~my_type()
	{
		cout<<"	~my_type()"<<endl;
	}
private:
	int _n;	
};
void test1()
{
	//	单个对象
	//操作符new  +  类型int +  初始化()
	
	int* ptr = new int(0);	//内置类型,申请好空间,可以显示初始化
	delete ptr;			//直接释放该空间,此处和free等价
	ptr = nullptr;

	my_type* mptr = new my_type;//自定义类型在申请好空间之后,new会调用该类的默认构造函数
	delete mptr;	//自定义类型delete会先调用该类的析构函数,然后释放该空间
	mptr = nullptr;
}
void test2()
{
	// 多个对象
	//操作符new  + 类型int  + 初始化{}
	int* ptr = new int[10]{0};		//申请一段连续的内存空间,可以显示初始化
	
	delete[] ptr;			//直接释放ptr指向的空间,此处与delete和free效果等价
	ptr = nullptr;

	my_type* mptr = new my_type[10];//在vs中,在申请连续多个自定义对象时,会多开4个字节,用来存储对象的个数,然后调用构造函数初始化每个对象,然后返回申请的起始地址的偏移4个字节之后的地址。
	
	delete mptr;	//在VS中,自定义类型delete会先在mptr指针向前偏移4个字节的位置取出对象个数来调用该类的析构函数析构每个对象,然后释放该空间
	mptr = nullptr;
}
使用new创建自定义对象空间时,如果没有默认构造,可以使用带参构造初始化。

注意new和delete匹配使用,new[]和delete[]匹配使用。

底层知识:

  • new操作符在底层实际会调用operaor new全局函数申请空间,失败抛异常;(底层含有malloc)
  • delete操作符在底层实际会调用operator delete全局函数释放空间;(底层含有free)

1.new和delete

  • new
    • 调用operator new全局函数申请空间
    • 在申请的空间上执行构造函数,完成对象的构造(自定义类型)
  • delete
    • 在空间上执行析构函数,完成对象的资源清理(自定义类型)
    • 调用operator delete全局函数释放对象空间

2.new[]和delete[]

  • new T[N]
    • 调用operator new[]全局函数,在该函数中实际调用operator new全局函数完成对N个对象的空间申请
    • 在申请的空间上执行N次构造函数(自定义类型)
  • delete []
    • 在空间上执行N个对象的析构函数,完成N个对象的资源清理(自定义类型)
    • 调用operator delete[]全局函数,实际调用operator delete全局函数释放空间
void test1()
{
	//my_type* ptr = (my_type*)malloc(sizeof(my_type));		等价
	my_type* ptr = (my_type*)operator new(sizeof(my_type));	//申请空间
	new (ptr)my_ptr(3);	//定位new表达式,调用构造函数
	

	ptr->~my_type();	//显示调用析构函数
	//	free(ptr);					等价
	operator delete(ptr);			//释放空间
	ptr = nullptr;
}
void test2()
{
	my_type* ptr = new my_type(3);	//申请空间+调用构造

	delete ptr;			//调用析构+释放空间
	ptr = nullptr;
}

二者关系

最后我们总结一下,两种管理方式的区别

mallloc/freenew/delete
函数操作符
malloc申请空间需要手动计算大小new 申请空间只需指定对象类型,可指定个数
malloc不会初始化new可以初始化
malloc返回的是void*,需要强转new返回的是空间对象类型的指针
malloc失败返空指针new失败抛异常
申请自定义类型对象,不会调用构造和析构申请自定义类型对象,会自动调用构造和析构

希望该片文章对您有帮助,请点赞支持一下吧😘💕

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

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

相关文章

HTML讲解(二)head部分

目录 1. 2.的使用 2.1 charset 2.2 name 2.2.1 describe关键字 2.2.2 keywords关键字 2.2.3 author关键字 2.2.4 http-equiv 小心&#xff01;VS2022不可直接接触&#xff0c;否则&#xff01;没这个必要&#xff0c;方源面色淡然一把抓住&#xff01;顷刻炼化&#x…

spring springboot 日志框架

一、常见的日志框架 JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j.... 注意&#xff1a;SLF4j 类似于接口 Log4j &#xff0c;Logback 都是出自同一作者之手 JUL 为apache 公司产品 Spring&#xff08;commons-logging&#xff09;、Hibernate&#xff08;jboss…

实力再证|海云安连续三年荣登中国网络安全产业联盟(CCIA)榜单,蝉联两届“中国网安产业成长之星”

9月6日&#xff0c;中国网络安全产业联盟&#xff08;CCIA&#xff09;正式公布了2024年中国网安产业竞争力50强、成长之星、潜力之星榜单&#xff0c;据悉&#xff0c;本次榜单调研共历时数月&#xff0c;从多个维度对调研企业进行了全面评估分析&#xff0c;遴选出2024年中国…

Thingsboard规则链:GPS Geofencing Filter节点详解

引言 GPS Geofencing Filter节点具体作用 使用教程 源码浅析 应用场景与案例 物流与运输 农业智能化 城市安全管理 结语 http://ThingsBoard从入门到实战课程&#xff0c;深入透析底层原理&#xff0c;快速搭建自己的IOT平台_哔哩哔哩_bilibili 引言 在物联网技术迅速发…

Linux文件IO(一)-open使用详解

在 Linux 系统中要操作一个文件&#xff0c;需要先打开该文件&#xff0c;得到文件描述符&#xff0c;然后再对文件进行相应的读写操作&#xff08;或其他操作&#xff09;&#xff0c;最后在关闭该文件&#xff1b;open 函数用于打开文件&#xff0c;当然除了打开已经存在的文…

2023年全国研究生数学建模竞赛华为杯C题大规模创新类竞赛评审方案研究求解全过程文档及程序

2023年全国研究生数学建模竞赛华为杯 C题 大规模创新类竞赛评审方案研究 原题再现&#xff1a; 现在创新类竞赛很多&#xff0c;其中规模较大的竞赛&#xff0c;一般采用两阶段&#xff08;网评、现场评审&#xff09;或三阶段&#xff08;网评、现场评审和答辩&#xff09;评…

C#和数据库高级:抽象类和抽象方法

文章目录 一、为什么使用抽象类和抽象方法&#xff1f;1.1、父类与子类的相互转换 二、抽象类和抽象方法2.1、抽象类的定义和方法声明规范2.2、使用继承多态的机制解决问题 三、抽象类的概念和使用特点总结 一、为什么使用抽象类和抽象方法&#xff1f; 1.1、父类与子类的相互…

Facebook的用户隐私保护:从争议到革新

Facebook早期的数据收集方式引发了隐私担忧。平台的快速增长和用户数据的大规模收集使得隐私问题逐渐显现。尤其是在2018年&#xff0c;剑桥分析事件暴露了数千万用户数据被不当使用的问题。这一事件揭示了Facebook在数据保护方面的严重漏洞&#xff0c;引发了公众对隐私保护的…

拓扑排序基础

拓扑排序简要介绍及应用场景 拓扑排序&#xff1a;对图中所有节点进行排序&#xff0c;保证每个节点的前置节点都在这个节点之前。 【使用要求】&#xff1a;有向图&#xff0c;无环 拓扑排序的顺序可能不只一种。拓扑排序也可以用来判断图中有没有环存在。 拓扑排序步骤&a…

【结构型】树形结构的应用王者,组合模式

目录 一、组合模式1、组合模式是什么&#xff1f;2、组合模式的主要参与者&#xff1a; 二、优化案例&#xff1a;文件系统1、不使用组合模式2、通过组合模式优化上面代码优化点&#xff1a; 三、使用组合模式有哪些优势1、统一接口&#xff0c;简化客户端代码2、递归结构处理方…

maxcompute使用篇

文章目录 maxcompute使用篇1.mongoDB与maxcompute 进行数据同步1.1 基本类型的数据1.2部分复杂类型的数据 2.maxcompute中复杂数据类型解析2.1 get_json_object2.2 json_tuple2.3 处理json几种失效的情况:2.4 STR_TO_MAP、MAP_KEYS2.5 regexp_replace2.6 FROM_JSON2.7 nvl2.8 t…

基于matlab的通信系统设计及仿真

文章目录 前言资料获取设计介绍功能介绍设计程序具体实现截图参考文献设计获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设…

PHP邮箱系统:从入门到实战搭建教程指南!

PHP邮箱系统配置教程&#xff1f;如何选用合适的PHP邮箱系统库&#xff1f; 为了满足个性化和定制化的需求&#xff0c;许多开发者选择使用PHP来搭建自己的邮箱系统。AokSend将带你从入门到实战&#xff0c;详细介绍如何搭建一个功能完善的PHP邮箱系统。 PHP邮箱系统&#xf…

谈谈你对线程池的了解

一、什么是线程池 线程池是一种创建和管理线程的技术。 二、怎么创建线程池 通过Executors工具类的静态方法&#xff0c;创建线程池。创建ThreadPoolExecutor对象&#xff0c;按照业务需要&#xff0c;自定义线程参数&#xff0c;创建线程池。 三、线程池的状态有哪些 线程池的…

VMware vCenter Server 8.0U3b 发布下载,新增功能概览

VMware vCenter Server 8.0U3b 发布下载&#xff0c;新增功能概览 Server Management Software | vCenter 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-vcenter-8-u3/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysi…

VirtualBox7.1.0 安装 Ubuntu22.04.5 虚拟机

环境 &#xff08;1&#xff09;宿主机系统&#xff1a;Windows10 &#xff08;2&#xff09;虚拟机软件&#xff1a;VirtualBox7.1.0 &#xff08;3&#xff09;虚拟机系统&#xff1a;Ubuntu 22.04.5 LTS (Jammy Jellyfish) 步骤 &#xff08;1&#xff09;第一步 &…

Python基础(七)——PyEcharts数据分析(面向对象版)

四、使用PyEcharts数据分析案例&#xff08;面向对象版&#xff09; 【前言&#xff1a;为了巩固之前的Python基础知识&#xff08;一&#xff09;到&#xff08;五&#xff09;&#xff0c;并为后续使用Python作为数据处理的好帮手&#xff0c;我们一起来用面向对象的思想来理…

并发编程 - 锁(@synchronized)

引言 在前面的博客中&#xff0c;我们已经讨论了锁在多线程编程中的重要性&#xff0c;主要是为了解决多线程同时访问同一片共享数据时发生的竞争条件&#xff08;race conditions&#xff09;&#xff0c;导致数据不一致和崩溃问题。 并且介绍了一个在Objective-C中&#xf…

mysql笔记7(单表查询)

文章目录 1. select① 从伪表里查数据(可以结合第3点dual理解数据来源)select 文字 ;做计算&#xff1a;select 算式;select 文字( 或算式) as 别名;(as 用于起别名&#xff0c;可省略) ② 从真实表里查数据select * from 表名;select 字段名&#xff0c;字段名 from 表名; 2. …

centos远程桌面连接windows

CentOS是一款广泛使用的Linux发行版&#xff0c;特别是在服务器领域。很多企业和个人用户会选择远程连接到CentOS进行操作和维护。虽然CentOS自带了一些远程桌面解决方案&#xff0c;但它们在使用上存在一些局限性。接下来&#xff0c;我将介绍如何实现CentOS的远程桌面连接&am…