首页 > 系统相关 >C++中的内存管理

C++中的内存管理

时间:2024-10-24 23:45:37浏览次数:3  
标签:free malloc 管理 C++ 空间 内存 operator new delete

下图是C++的内存储存管理的方式

   由图不难得知,局部变量是储存在栈中的,而malloc,calloc,realloc开辟出来的空间是储存在堆中的,全局数据和静态变量储存在数据段中,也叫静态区.代码段存的是可执行代码和只读常量。

  C 语言中动态内存管理方式: malloc/calloc/realloc/free   C++ 内存管理方式   语言内存管理方式在 C++ 中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因 此 C++ 又提出了自己的内存管理方式: 通过 new和delete 操作符进行动态内存管理 使用方法:
#include<iostream>
using namespace std;

void test()
{
	int* p1 = new int;//动态申请一个int 类型的空间
	int* p2 = new int(1); //动态申请一个int 类型的空间并初始化为1
	cout << *p2 << endl;

	int* p3 = new int[3]; //动态申请三个int 类型的空间
	int* p4 = new int[3] {1,2,3}; //动态申请三个int 类型的空间并初始化为1,2,3

	for (int i = 0; i < 3; i++)
	{
		cout << *(p4+i) << endl;
	}

	delete p1;
	delete p2;
	delete[] p3;
	delete[] p4;



}

int main()
{
	test();

	return 0;
}

运行结果

未执行delete时 执行delete后释放空间 new delete 操作自定义类型 自定义类型中使用new和delete会自动申请类型大小的空间和自动调用构造函数和相应的析构函数并释放空间
#include<iostream>
using namespace std;

class A
{ 
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a = 0)" << endl;
	}

	~A()
	{
		cout << "~A()" << endl;

	}
private:
	int _a;

};

int main()
{

	A* P1 = new A;

	A* P2 = new A(1);

	A* P3 = new A[3]{ 1,2,3 };

	delete P1;
	delete P2;
	delete[] P3;


}

运行结果表明确实调用了构造函数和析构函数

注意:在申请自定义类型的空间时, new 会调用构造函数, delete 会调用析构函数,而 malloc free 不会operator new operator delete 函数 new delete 是用户进行 动态内存申请和释放的操作符operator new operator delete 是 系统提供的 全局函数new 在底层调用 operator new 全局函数来申请空间, delete 在底层通过 operator delete 全局函数来释放空间。 /* operator new :该函数实际通过 malloc 来申请空间,当 malloc 申请空间成功时直接返回;申请空间 失败,尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否 则抛异常。 */ void * __CRTDECL operator new ( size_t size ) _THROW1 ( _STD bad_alloc ) { // try to allocate size bytes void * p ; while (( p = malloc ( size )) == 0 ) if ( _callnewh ( size ) == 0 ) { // report no memory // 如果申请内存失败了,这里会抛出 bad_alloc 类型异常 static const std::bad_alloc nomem ; _RAISE ( nomem ); } return ( p ); } /* operator delete: 该函数最终是通过 free 来释放空间的 */ void operator delete ( void * pUserData ) { _CrtMemBlockHeader * pHead ; RTCCALLBACK ( _RTC_Free_hook , ( pUserData , 0 )); if ( pUserData == NULL ) return ; _mlock ( _HEAP_LOCK ); /* block other threads */ __TRY /* get a pointer to memory block header */ pHead = pHdr ( pUserData ); /* verify block type */ _ASSERTE ( _BLOCK_TYPE_IS_VALID ( pHead -> nBlockUse )); _free_dbg ( pUserData , pHead -> nBlockUse ); __FINALLY _munlock ( _HEAP_LOCK ); /* release other threads */ __END_TRY_FINALLY return ; } /* free 的实现 */ #define free(p) _free_dbg(p, _NORMAL_BLOCK) 通过上述两个全局函数的实现知道, operator new 实际也是通过 malloc 来申请空间 ,如果 malloc 申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施 就继续申请,否则就抛异常。 operator delete 最终是通过 free 来释放空间的 new delete 的实现原理 内置类型 如果申请的是内置类型的空间, new 和 malloc , delete 和 free 基本类似,不同的地方是: 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 来释 放空间 定位 new 表达式 (placement-new)  定位 new 表达式是在 已分配的原始内存空间中调用构造函数初始化一个对象使用格式: new (place_address) type 或者 new (place_address) type(initializer-list) place_address 必须是一个指针, initializer-list 是类型的初始化列表 使用场景: 定位 new 表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如 果是自定义类型的对象,需要使用 new 的定义表达式进行显示调构造函数进行初始化。
class A
{
public:
A(int a = 0)
: _a(a)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a;
};
// 定位new/replacement new
int main()
{
// p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没
有执行
A* p1 = (A*)malloc(sizeof(A));
new(p1)A; // 注意:如果A类的构造函数有参数时,此处需要传参
p1->~A();
free(p1);
A* p2 = (A*)operator new(sizeof(A));
new(p2)A(10);
p2->~A();
operator delete(p2);
return 0;
}
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 在释放空间前会调用析构函数完成 空间中资源的清理释放 补充:free和new不能搭配使用,否则有些情况下会报错
#include<iostream>
using namespace std;

class A
{ 
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a = 0)" << endl;
	}

	~A()
	{
		cout << "~A()" << endl;

	}
private:
	int _a;

};

int main()
{

	
	A* P3 = new A[3]{ 1,2,3 };

	free(P3);

	return 0;
}

这个代码中虽然释放掉了空间,但是没有正确调用析构函数会导致崩溃

标签:free,malloc,管理,C++,空间,内存,operator,new,delete
From: https://blog.csdn.net/2301_79389054/article/details/143206463

相关文章

  • C++模板
    模板初阶如何实现一个通用的加法函数?我们可以类似这样使用函数重载的方法进行编写intsum(int&a,int&b){ returna+b;}doublesum(double&a,double&b){ returna+b;}使用函数重载虽然可以实现,但是有一下几个不好的地方:1.重载的函数仅仅是......
  • 如何使用数据分析进行项目管理
    项目管理是一项要求对不断变化的项目元素保持敏锐洞察的专业工作,而数据分析则是项目管理的关键工具之一。使用数据分析进行项目管理包括:监控项目进度与状况、优化资源分配、预测项目风险与结果、改进决策制定流程、提升团队协作与沟通效率。其中,监控项目进度与状况是数据分析在项......
  • C++ Mutex
    定义互斥量可以使用在各种方面,常用在对共享数据的读写上。如果有多线程读写一个数据,那么想要保证线程安全,必须对共享变量的读写上锁头文件#include<mutex>类型std::mutex,最基本的Mutex类std::recursive_mutex,递归Mutexstd::time_mutex,限时Mutexstd::recursive_timed_......
  • 每日OJ题_牛客_DP10最大子矩阵_二维前缀和_C++_Java
    目录牛客_DP10最大子矩阵_二维前缀和题目解析C++代码Java代码牛客_DP10最大子矩阵_二维前缀和最大子矩阵_牛客题霸_牛客网(nowcoder.com)描述:        已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1*1)子矩......
  • 织梦重置mysql数据库密码忘记_织梦cms管理员密码忘记了怎么重置找回?
    方法一:通过phpMyAdmin登录数据库,在dede_admin表中重置密码登录数据库管理界面登录网站所在的虚拟主机或服务器,进入数据库管理(phpMyAdmin)界面。选择网站所用的MySQL数据库。找到并浏览dede_admin表在数据库中找到dede_admin表。点击表名,选择“浏览”选项,进入表数据......
  • 【子项目:命令系统(Command System)】C++自制命令系统( 开发ing | 踩坑记录 )
    项目背景在某一项目中,遇到了需要自制命令系统的需求,而这个模块的复用性很高,因此单独拉出来做一个子项目更新日志[2024.10.15-10:00]增项目进度----[2024.10.1510:00]----首先实现最基础的输入输出功能,用std::getline读入行再分割成字符串数组-main.cpp#include......
  • 国内外比较好用的项目管理软件分别有哪些
    项目管理软件在国内外均有广泛应用,助力企业高效协同和管理。国内优秀的项目管理软件包括:1.Teambition;2.钉钉项目管理;3.Tower。国外知名的项目管理软件有:1.Asana;2.Trello;3.Jira。其中,Teambition以其出色的团队协作和灵活的项目管理功能受到许多企业的青睐。一、国内优秀......
  • 面试华为遇到了经典动态规划题 - 怎么用go、C++进行编程解决
    华为的知名很大程度上源自于在经历过被美国的制裁和打压后不仅撑住了,而且还做出了相对于自己来说技术进步程度很大的芯片​。这是一个不小的成绩​。从个人的角度上来说,华为是最难进的一家大公司之一,它的面试标准很严格​。这不仅是筛选人才,在某种程度上来说也是由于求职市场......
  • 【C++干货篇】——C/C++内存管理
    【C++干货篇】——C/C++内存管理文章目录【C++干货篇】——C/C++内存管理1.C/C++内存分布1.1静态区/数据段:1.2常量区/代码段:1.3栈:1.4堆:1.5.内存映射区:2.C语言中动态内存管理方式:`malloc/calloc/realloc/free`1.`malloc`2.`calloc`3.`realloc`总结3.C++内存管理方......
  • 图书管理系统的简单实现
    文章目录图书系统逻辑分析各种操作功能的实现完整代码  个人主页  JavaSE专栏图书系统逻辑分析该程序设置有三个包,user包,book包,operation包。book包中包含对于书的一些信息和操作;operation包中包含有对书的所有操作功能;user包中包含用户的一些信息......