C++动态内存管理( 深度解析·new-delete-new[]-delete[] )

 C中的动态内存方式    

 整体代码测试环境:VS 08 

 1.堆上申请内存空间                    

(1)malloc申请 内存空间

void* malloc(字节数)

 说明:这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。  

  •  如果开辟成功,则返回一个指向开辟好空间的指针。 
  •  如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。 
  •  返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
  •  如果参数size为0,malloc的行为是标准是未定义的,取决于编译器

(2)calloc申请内存空间

void* calloc(元素个数,元素类型字节)-->0 初始化

说明:函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为 0。 

  •    与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0

(3)realloc申请内存空间

void* realloc(void* p, size_t size)

 说明:ptr 是要调整的内存地址  

  •    size 调整之后新大小 返回值为调整之后的内存起始位置。 
  •    这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。 
  •    realloc在调整内存空间的是存在两种情况: 

注意:他们三个都需要free来释放,否则会发生内存泄漏问题

 2.栈上申请内存空间                    

使用_alloca在栈上动态开辟内存,栈上开辟的内存由编译器自动维护,不需要用户显示释放

<strong>C++的动态内存管理方式</strong>

C++中的动态内存方式

1.C++中通过new和delete运算符来进行动态内存管理

                                         

                                                                               图 new和delete的使用方法

注:new申请出来的空间无需判空

      new[]和delete[]一定要搭配使用,否则可能出现内存泄漏甚至崩溃的问题

class Test
{
public:
	Test()
	{
		//_p = new int(10);
		cout<<"Test():"<<this<<endl;
	}
	~Test()
	{
		/*if(_p)
		{
			delete _p;
		}*/
		cout<<"~Test()"<<this<<endl;
	}

	int data;
	//int* _p;
};



void FunTestc()
{
	Test *p1 = (Test*)malloc(sizeof(Test)); //没有调用构造函数,不是一个完整的Test类型对象,_p指向的空间是随机值
	Test *p2 = (Test*)malloc(sizeof(Test));//屏蔽_p
	delete p1;
	delete[] p2;

	Test *p3 = new Test;
	Test *p4 = new Test;
	free(p3);
	delete[] p4;

	Test *p5 = new Test[10];
	Test *p6 = new Test[10];
	free(p5);
	delete p6;
}

int main()
{
	FunTestc();
	return 0;
}

一经调试,会发现走到 delete[] p2 的位置发生了中断,把 delete[] p2 屏蔽掉后,再往下走没有任何问题,但是一走到 delete[] p4的位置就又发生了中断 ,具体原因我们在下面进行剖析

但是如果在类里面加入 int* _p和析构函数,就会发现在一开始的mian函数里面的 p1就发生了错误,原因是malloc在开辟的空间的时候,没有调用构造函数,也就是没有完成对对象的赋值,所以没有创建一个完整的Test对象,自然也就崩溃了

那么问题来了,既然C中有了malloc/free来管理内存空间,为什么C++还要定义new/delete运算符来动态管理内存空间?(面试题)

1.他们都是动态管理内存的入口

2.malloc/free是C/C++标准库的函数,而new/delete是C++的操作符

3.malloc/free只是动态分配内存空间/释放空间,而new/delete除了分配空间还会调用构造函数和析构函数进行初始化和清理(清理成员)

4.malloc/free需要手动的计算类型大小且返回值是void*,需要用户自定义其类型,new/delete可以自己计算类型的大小,返回对应的类型指针

2.深度剖析new/new[]/delete/delete[]

class Test
{
public:
	Test()
	{
		_data = 100;
		cout<<"Test():"<<this<<endl;
	}

	~Test()
	{	
		cout<<"~Test()"<<this<<endl;
	}

	int _data;
};

int main()
{
	Test* pA = new Test;
	delete pA;

	/*Test* pA = new Test[10];
	delete[] pA;*/
	return 0;
}
  • new

    我们在main函数的第一句代码处下一个断点,然后往里面一走,就会发现里面调用的是这样的:

其实就是将malloc重新封装了一下

总结一下new的机制:

  • delete

所以delete做的只有两件事:    调用pA对象指向的析构函数,对打开的文件进行关闭

                                               调用operator delete标准库函数来释放该对象的内存空间 ,传入函数的参数为                                                     pA 的值,也就是0x007d290   

  • new T[N]

经过调试发现new T[N]背后做了这些事

 

  • .delete[]

那么delete[]就很简单了

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值