数组的长度都是预先就定好了的,不允许出现长度不确定的数组。但是在日常的使用中需要定义的数组大小往往取决于实际中数据量的多少,在这种情况下我们或许会想到分配尽可能大的空间不就行了,但是尽可能大究竟是多大呢?这个不确定可能会导致空间不足或者空间浪费,为了解决这个问题,便有了“动态内存分配”,C++便是通过new/delete来进行动态内存管理。
new/delete是什么?
我们定义一个类方便下面使用:
class A
{
public:
A()//构造函数
{
cout << "A()" << endl;
}
~A()//析构函数
{
cout << "~A()" << endl;
}
};
在C++中我们通过new运算符来进行动态内存分配
1、动态分配单个空间
A* pa = new A;
得到的结果是:动态分配出了一块大小为sizeof(A)字节的内存空间,并调用对应的构造函数将其初始化。
示例:
2、动态分配一个数组空间
A* pa = new A[N];
得到的结果是:动态分配出了一块大小为 sizeof(A)*N 字节的内存空间,并多次调用对应的构造函数将其初始化。
示例:
从上面我们可以发现,new和malloc有所不同,首先在使用的时候我们不用再手动的求出想要开辟空间的大小,其次new会自动调用相应的初始化所开辟的空间。
在C++中我们通过delete运算符来释放动态分配的内存空间
delete pa;
得到的结果是:释放之前动态申请的空间,并调用相应的析构函数进行清理。
delete[] pa;
得到的结果是:释放之前动态申请的空间,并多次调用相应的析构函数进行清理。
从上面我们可以发现,delete和free有所不同,首先是我们再释放一段数组空间时需加上[],其次delete会自动调用相应的析构函数来清理释放的空间。
new/delete其实做了两件事:
1.调用相应的operator new申请内存//调用相应的operator delete释放内存
2.调用相应的构造函数初始化//调用相应的析构函数清理
想要具体了解new/delete少不了operator new/operator delete
operator new和operator delete
函数原型
void* operator new (size_t size);//申请单个空间 void operator delete (void* ptr) //申请一个数组 void* operator new[] (size_t size); //释放单个空间 void operator delete[] (void* ptr) //释放一个数组
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常
operator delete: 该函数最终是通过free来释放空间的
operator new[] 和 operato delete[]: 就是多次循环得进行申请或者释放
注:new/delete 和 new [] delete [] 最好配套使用,不然容易造成内存泄漏
new/delete/malloc/free的联系和区别
联系
1、存储方式相同,他们都是动态申请堆上的空间,所申请的空间不会自动被系统回收,需要手动释放。
2、对于内置类型,比如char,int,double等,他们之间得到的效果一样。
3、他们都是配套使用的,malloc对free,new对delete。如果不配套使用可能会发生内存泄露。
区别
1、malloc/free是C语言库里的函数,需要引用头文件,返回的是void* ,使用时一般会强转。new/delete是C++的运算符,直接带回具体类型的指针。
2、对于内置类型,new会先申请空间,然后调用相应的构造函数进行初始化,malloc只会申请。delete会先调用相应的析构函数进行清理,然后再释放,free只会释放。
3、malloc申请空间时需要手动计算大小并传递,new只需要再后面跟上对应的类型即可。
4、malloc申请失败会直接返回空,而new申请失败则会抛异常(如果设置了应对措施则会继续申请,失败就抛异常)。