在学习c++内存管理时,学习new[]时,总是与delete配对使用,这是为什么呢?在内置类型无需析构的条件下情况下不能申请空间时用new[]而释放空间时用free吗?反正delete底层也是调用free,并且内置类型无需析构也不会造成内存泄漏.那不如我们实践一下吧.
首先我们先建立一个简单的类A,如下.因为类A里面没有申请空间,所以A不析构也不会造成内存泄漏.
cpp
class A
{
public:
A(int a = 0)
:_a(a)
{
cout << "A(int a = 0)" << endl;
}
//~A()
//{
// cout << "~A()" << endl;
//}
private:
int _a;
};
下面我们就来试一下用new[]来开空间,用free来释放吧
cpp
int main()
{
A* pa = new A[10];
free(pa);
return 0;
}
整体代码如下图

运行后结果见下

程序正常运行,没有崩溃.这是否说明可以不配对使用呢?
大家可能已经发现了,在上面我建立A类时把A的析构给屏蔽掉了,现在我们把A的析构放开,在进行上述实验.
整体代码如下

执行结果见下

这次竟然崩溃了,这是为什么呢?
从现象上来看是类里面是否显示写析构函数造成的影响,显示写了析构就会崩溃,不显示写句不会有事.
在进行调试后,内存窗口中在地址处输入pa,可看见下图结果从pa向后的40个字节也就是new的对象的空间都被正常初始化了

但是转到反汇编我们发现new这个语句开了48字节的空间.

这是什么原因呢?我们在去内存窗口看一下,向上条一行可以看到下图现象

可以看到new[]向前开了八个字节的空间去存储了new的对象的个数也就是0ah(10),可以概括成下图形式.记录这个对象个数是为了知道之后释放空间时要调用多少次的析构函数去析构new[]出来的对象.

而此时pa并没有指向开辟空间中的最前面,根据free()的要求,一块空间只能从头进行free不能从中间free所以出现了崩溃.
是否向前开辟空间储存对象个数取决于对象是否显示写析构函数,显示写析构了,编译器就认为释放空间时需要调用析构从而在前面多开一段空间去存储个数,如果没有显示写析构,则不用多开辟.这就是出现上面结果的原因.
在进行delete[] 时,内部会将pa指向的位置进行修正,修正后在进行free()的调用,所以不会出现问题. 但是delete和free都不会对pa进行修正.


综上,进行对空间的开辟和释放时函数要配对使用.