C++中的new/delete与malloc/free

知识储备:

内存泄漏:通俗的来说内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。

常见的几种内存泄漏:

void MemoryLeaks()
{
	// 1、内存申请了忘记释放
	int *pTest = (int *)malloc(10*sizeof( int));
	assert(NULL != pTest);
	DoSomething();

	// 2、程序逻辑错误,以为释放了,实际内存泄露
	int *pTest1 = (int *)malloc(10*sizeof( int));
	int *pTest2 = (int *)malloc(10*sizeof( int));
	DoSomething();
	pTest1 = pTest2;
	free(pTest1);
	free(pTest2);

	// 3、程序访问越界操作,将堆破坏
	char *pTest3 = (char *)malloc(5);
	strcpy(pTest3, "Memory Leaks!");
	free(pTest3);

	// 4、释放时传入的地址和申请时的地方不相同
	int *pTest4 = (int *)malloc(10*sizeof( int));
	assert(NULL != pTest4);
	pTest4[0] = 0;
	pTest4++;
	DoSomething();
	free(pTest4);
}

new/delete:

1.C++中的操作符

2.不需要头文件支持。

malloc/free:

1.是函数。

2.需要头文件支持。<malloc.h>

new和malloc:

new做两件事,一是分配内存,二是调用类的构造函数

new建立的是一个对象,而malloc分配的是一块内存;new建立的对象可以用成员函数访问,不要直接访问它的地址空间;malloc分配的是一块内存区域,用指针访问,可以在里面移动指针;new出来的指针是带有类型信息的,而malloc返回的是void指针。

delete和free:

delete先调析构函数,再释放空间

free释放一块指定的内存空间

new :

1. 调用operator new分配空间。
2. 调用构造函数初始化对象。

delete:

1. 调用析构函数清理对象
2. 调用operator delete释放空间

new[]:

1. 调用operator new分配空间。
2. 调用N次构造函数分别初始化每个对象

delete[]:

1. 调用N次析构函数清理对象。

2. 调用operator delete释放空间。

new/delete 和 malloc/free的区别和联系:

1. 它们都是动态管理内存的入口。
2. malloc/free是C/C++标准库的函数,new/delete是C++操作符。
3. malloc/free只是动态分配内存空间/释放空间。而new/delete除了分配空间还会调用构造函数和析构函数进行初始化与清理(清理成员)。
4. malloc/free需要手动计算类型大小且返回值会void*,new/delete可自己计算类型的大小,返回对应类型的指针。

在调用new和delete时可以发现,在底层new实际调用的是operator new,delete实际调用的是operator delete。



说在前面:

标准库函数operator new 和operator delete的命名容易让人误解,与其他operator函数不同,这些函数没有重载new或者delete表达式,实际上,我们不能重定义new和delete表达式的行为。

void * operator new (size_tsize);
void operator delete (size_tsize);
void * operator new [](size_tsize);
void operator delete[] (size_tsize);

new -->   operator new (进一步调用malloc申请空间) + 构造函数
delete ->析构函数 +  operator delete (调用free)

operator new()->失败抛出异常
malloc ->失败返回错误码

由此我们可以推出new在调用内存真正做了什么:


总结:

1. operator new/operator delete operator new[]/operator delete[] 和malloc/free用法一样。
2. 他们只负责分配空间/释放空间,不会调用对象构造函数/析构函数来初始化/清理对象。
3. 实际operator new和operator delete只是malloc和free的一层封装

new[count]:

一般情况下,会开辟出4字节来存放count,但是编译器在此处会进行优化。有时候也不会开辟空间。如析构函数可调可不调时(自己写的构造函数一定要调),或不需要清理资源时,编译器优化为不需要调用析构函数,由此不会开辟内存空间


动态内存管理:

没有调析构和构造,  指针的偏移位置不正确

可能崩溃:
new--delete[] delet时指针往前偏移了4字节(误认为)
new[]-- free free没往前偏移4字节
可能会内存泄漏:
new--free

#include <iostream>

using namespace std;

class AA
{
public:
	AA(size_t size = 10)
		:_size(size)
		,_a(0)
	
	{
		cout << "AA()" << endl;
		if (_size > 0)
			_a = new int[_size];
	}
	~AA()
	{
		cout << "~AA()" << endl;
		if (NULL != _a)
		{
			delete[]_a;
			_a = NULL;
			_size = 0;
		}
	}

private:
	int *_a;
	size_t _size;
};

int get_size()
{
	return 10;
}

int main()
{
	int *p0 = new int[get_size()];	//括号内大小必须是整形,但不必是常量
	
	//内置类型也有构造函数,但是不能被重写
	int p1 = 6;				//初始化为10
	p1 = int();				//构造函数,初始化为0
	p1 = int(20);			//初始化20

	AA* p2 = new AA;
	delete p2;		//匹配: 一次构造,一次析构
	delete[]p2;		//不匹配:崩溃  越界释放
	free(p2);		//不匹配:可能会内存泄露

	AA* p3 = new AA[10];
	delete p3;		//不匹配:10次构造,一次析构,内存释放位置错误
	delete[]p3;		//匹配:
	free(p3);		//不匹配:10构造,0析构,内存释放位置错误

	int* p4 = new int[10];
	delete p4;		//正确,不调析构,无内存需清理,指针不会发生偏移
	delete[]p4;		//匹配
	free(p4);			//不崩溃,但是不代表正确使用

	AA* p5 = new AA[];					//
	delete p5;		//崩溃
	delete[]p5;		//匹配
	free(p5);		//崩溃

	int* p4 = new int;
	int* p5 = new int(3);
	int* p6 = new int[3];
	int* p7 = (int*)malloc(sizeof (int));

	delete[] p4;		//不崩溃,
	delete p5;		//不崩溃
	free(p5);			//no
	delete p6;		//no
	delete p7;			//no

	int *p = new int[10]{0};

	system("pause");
	return 0;
}

new和delete、new[]和delete[]一定匹配使用,一定匹配使用,一定匹配使用!!!

C库malloc/free等来动态管理内存,为什么C++还要定义new/delete运算符来动态管理内存呢?

malloc 与free 是C++/C 语言的标准库函数,new/delete 是C++的运算符。它们都可用于申请动态内存和释放内存。
对于非内部数据类型的对象而言,光用maloc/free 无法满足动态对象的要求。对象在创建的同时要自动执行构造函数, 对象在消亡之前要自动执行析构函数。由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值