我们学习完了c++类的定义以及其中的默认成员函数,并且也了解了一些其他的功能接下来我们就要对内存管理进行一个讲解。其实在c语言阶段,我们简单接触了一下malloc等函数,这些是动态分配内存的重要函数。接下来我们就要引进c++专门的动态分配内存空间的方法。
首先,我们要学两个操作符,分别是new和delete,他们的用法跟malloc和free类似,但是malloc和free的本质是函数,而new和delete是操作符,在使用方面更加的简洁。但是单单是简介的话,那也不可能单独给他开一个操作符,接下来我们就来看看他们的厉害之处。
int* p1 = new int;
int* p2 = new int[10];
int* p3 = new int(1);
int* p4 = new int[10] {1, 5, 4, 6, 9};
delete p1;
delete p2;
delete p3;
delete p4;
首先我们来看内置类型的new,我们开空间的方法一共有四种形式,分别对应1,2,3,4行。其中1,3行是开一个大小为int的空间,3是给p3所指空间的内容初始化了。2,4行是开了大小为10个int的空间,而第4行是其初始化的方式。我们来看结果:
我们可以看到,空间确实是开了,而且也初始化了,但是为什么p4后面的空间的值是0呢?原因是我们在初始化的时候,并没有给完,所以编译器会把它置为0,而没有初始化的话就默认只开了空间并不初始化。而delete看起来跟free并没有什么区别。
上述讲的是内置类型中new的用法,那么自定义类型的话呢。我们来看。
class A
{
public:
A(int b = 2)
:_b(b)
{
cout << "A()" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _b;
};
A* p5 = new A;
cout << "--------------------------" << endl;
A* p6 = new A(1);
cout << "--------------------------" << endl;
A* p7 = new A[5]{2,6,5};
cout << "--------------------------" << endl;
delete p5;
cout << "--------------------------" << endl;
delete p6;
cout << "--------------------------" << endl;
delete p7;
我们来看结果:
首先我们抛开错误先不看,我们来看运行过程中的结果,很明显我们可以看到,我们已经实现了p5,p6,p7三个指针的初始化,并且创建了几个对象,就调用了多少次构造函数。初始化方式跟内置类型差不多。但是在我们delete的时候,出了点小问题,其实问题出在delete p7的时候,我们这样释放的话,只会释放p7指向的地址的一个类型大小的空间,但是它申请了多个对象的空间,所以我们应该这样释放:
delete[] p7;
结果如下:
这样我们得到的就是正确的结果。
最后我们来总结一下,malloc/free和new/delete的区别:
1.malloc和free是函数,而new和delete是操作符。
2.new可以实现初始化,而malloc不行。
3.new可以直接给数据的个数与类型,而mallo得手动计算。
4.new不需要强转类型,而malloc需要。
5.malloc的失败会返回NULL,而new需要捕获异常。
6.malloc/free只会开空间,不会调用构造函数和析构函数。而new会调用构造函数完成初始化,delete在释放空间之前调用析构函数。