C++动态内存管理

对于C的动态内存管理可以参考本篇博客:
https://mp.youkuaiyun.com/postedit/79508975
new和delete
在c++中用new/delete动态管理对象;new[ ]和delete[ ] 动态管理对象数组。
注:new是申请空间,delete是释放空间
这里写图片描述
看下列例子:
这里写图片描述
注:malloc/free需要手动计算类型大小且返回值为void*,new/delete可自己计算类型大小,返回对应类型的指针;
动态内存管理:malloc/free 、new/delete、new[ ]/delete[ ]三个需要匹配使用,否则会出现内存泄漏甚至崩溃的问题。
内存管理
这里写图片描述
1.栈又叫堆栈,非静态局部变量/函数参数/返回值等等,栈是向下增长的。
2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。
3. 堆用于程序运行时动态内存分配,堆是可以上增长的。
4. 数据段–存储全局数据和静态数据。
5. 代码段–可执行的代码/只读常量。
C++其他内存管理接口
void * operator new (size_t size);
void operator delete (size_t size);
void * operator new [](size_t size);
void operator delete[] (size_t size);
上列4 个函数不是运算符重载
operqtor new函数new表达式
标准库函数operator new和operator delete的命名很容易让人误解,与其他operator函数(如operator=)不同,这些函数没有重载new或delete表达式。实际上,我们不能重定义new和delete表达式的行为。
通过调用operator new函数执行new表达式获得内存,并接着在该内存中构造一个对象,通过撤销一个对象执行delete表达式,并接着调用operator delete函数,以释放该对象使用的内存。
总结:1.operator new/operator delete 、operator new[ ]/operator delete [ ]和malloc/free用法一样,但operator new和operator new[ ]失败会抛异常。
2. 他们只负责分配空间/释放空间,不会调用对象构造函数/析构函数来初始化/清理对象。
3. 实际operator new和operator delete只是malloc和free的一层封装。
new/delete分别调构造和析构函数

class Array
{
public:
	Array(int size = 10)
		:_size(size)
		, _a(0)
	{
		cout << "构造" << endl;
		if (_size > 0)
		{
			_a = new int[_size];
		}
	}
	~Array()
	{
		cout << "析构" << endl;
		if (_a) 
		{
			delete[] _a;
			_a = 0;//置空
			_size = 0;
		}
   }
	
private:
	int* _a;
	int _size;
};
int main()
{
	Array* p1 = (Array *)malloc(sizeof(Array));
	//申请了对象p1的空间,并没有申请_a的空间
	Array* p2 = new Array; //申请_a的空间,并将_size初始化为10
	Array* p3 = new Array(20);//申请将__a的空间,size初始化为20
	cout << "new:p4" << endl;
	Array* p4 = new Array[3];//调三次构造函数
	//p4相当于数组,数组里存3个Array对象,每个对象的_a都申请了空间,_size都为10
	cout << "*******" << endl;
	free(p1);
	delete p2;
	delete p3;
	cout << "delete: p4" << endl;
	delete[] p4;//调了三次析构函数
	return 0;
}

new调构造函数
这里写图片描述
delete调析构函数
这里写图片描述
监视:
这里写图片描述
这里写图片描述
注:可以理解Array* p4 = new Array[3]会调三次构造函数,那为什么也会析构三次,怎么保存3的?后文会讲到。
【malloc/free和new/delete的区别和联系】

  1. 它们都是动态管理内存的入口。
  2. malloc/free是C/C++标准库的函数,new/delete是C++操作符。
  3. malloc/free只是动态分配内存空间/释放空间。而new/delete除了分配空间还会调用构造函数和析构函数进行初始化与清理(清理 成员)。
  4. malloc/free需要手动计算类型大小且返回值会void*,new/delete可自己计算类型的大小,返回对应类型的指针。
    总结:
    new做了两件事
  5. 调用operator new分配空间。
  6. 调用构造函数初始化对象。
    delete也做了两件事
  7. 调用析构函数清理对象
  8. 调用operator delete释放空间
    new[N]
  9. 调用operator new分配空间。
  10. 调用N次构造函数分别初始化每个对象。
    delete[]
  11. 调用N次析构函数清理对象。
  12. 调用operator delete释放空间。
    定位new表达式(replacemen版本)
    定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
    new (place_address) type
    new (place_address) type(initializer-list)
    place_address必须是一个指针,initializer-list是类型的初始化列表。
int main()
{
	// malloc/free + 定位操作符new()/显示调用析构函数,模拟 new和delete 的行为 
	Array* p1 = (Array*)malloc(sizeof(Array));     
	new(p1) Array(100);

	p1->~Array();  
	free(p1);

	// malloc/free + 多次调用定位操作符new()/显示调用析构函数,模拟 new[]和delete[] 的行为 
	Array* p2 = (Array*)malloc(sizeof(Array) * 10);//10个对象
	for (int i = 0; i < 10; i++)
	{
		new(p2 + i)Array;//需要将10个对象都构造初始化
	}

	for (int i = 0; i < 10; i++)
	{
		(p2+i)->~Array;//先调用析构清理10个对象
	}
	free(p2);//再整体释放空间
}

深度剖析new/delete和new[ ]/delete[ ]
new/delete
这里写图片描述
**new[ ]和delete[ ]**及解释如何知道析构N次:
这里写图片描述
注意:当用户没有定义析构函数或者是内置类型或基本类型不用多申请4个字节存对象个数:
这里写图片描述
这里写图片描述

Array *p3 = new Array;
delete[]p3; //有问题,会朝前清理4个字节

Array *p4 = new Array[10];
delete p4;//有问题,没有将多开四个字节空间释放

所以,对于malloc/free 、new/delete、new[ ]/delete[ ]三个需要匹配使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值