动态内存开辟new_delete
new作用:
1.申请空间2.调动构造函数初始化对象
delete作用:
1.调动析构函数析构对象
2.释放空间
通常定义变量(或对象),编译器在编译时都可以根据该变量(或对象)的类型知道所需内存空间的大小,从而系统在适当的时候为他们分配确定的存储空间。这种内存分配称为静态存储分配
有些操作对象只有在程序运行时才能确定,这样编译器在编译时就无法为他们预定存储空间,只能在程序运行时,系统根据运行时的要求进行内存分配,这种方法称为动态存储分配。所有动态存储分配都在堆区中进行。
当程序运行到需要一个动态分配的变量或对象时,必须向系统申请取得堆中的一块所需大小的存贮空间,用于存贮该变量或对象。
当不再使用该变量或对象时,也就是它的生命结束时,要显式释放它所占用的存贮空间,这样系统就能对该堆空间进行再次分配,做到重复使用有限的资源。
在C++中,申请和释放堆中分配的存贮空间,分别使用new和delete的两个运算符来完成,
类型名 指针变量名 = new 类型名(初始化式);
delete 指针变量名;
int *pi=new int(0); //用初始化式来显式初始化:
delete pi; //当pi生命周期结束时,
注意这时释放了pi所指的目标的内存空间,也就是撤销了该目标,称动态内存释放,但指针pi本身并没有撤销。
对于数组进行动态分配的格式为:
类型名 指针变量名=new 类型名[下标表达式];
Delete [ ]指针变量名;
int *pi = new int[10]; //创建一个int类型的数组
delete []pi; //删除数组
两式中的方括号是非常重要的,两者必须配对使用。如果delete语句中少了方括号,因编译器认为该指针是指向数组第一个元素的指针,会产生回收不彻底的问题(只回收了第一个元素所占空间),加了方括号后就转化为指向数组的指针,回收整个数组。
delete [ ]的方括号中不需要填数组元素数,系统自知。即使写了,编译器也忽略。
例子:
<span style="font-size:18px;">class Test
{
public:
Test(int d = 0):data(d)
{}
~Test()
{}
private:
int data;
}
int main()
{
Test *pt = new Test(100); //创建一个对象,并初始化为100
delete pt;
Test *pa = new Test[100]; //创建100个对象,按默认值初始化
delete []pa;
return 0;
}</span>
强调:由堆区创建对象数组,只能调用缺省的构造函数,不能调用其他任何构造函数。
如果没有缺省的构造函数,则不能创建对象数组。
malloc和free与new和delete的区别:
C语言中的malloc只负责申请空间,free只负责释放空间
C++语言中的new不仅负责空间的申请,还负责为对象初始化,
delete不仅负责空间的释放,之前还要析构对象
指针使用的几个问题:
1.动态分配失败。返回一个空指针(NULL),表示发生了异常,堆资源不足,分配失败。
2.指针删除与堆空间释放。删除一个指针p(delete p;)实际意思是删除了p所指的目标(变量或对象等),
释放了它所占的堆空间,而不是删除p本身,释放堆空间后,p成了空悬指针。
3.内存泄漏(memory leak)和重复释放。new与 delete 是配对使用的, delete只能释放堆空间。
如果new返回的指针值丢失,则所分配的堆空间无法回收,称内存泄漏,同一空间重复释放也是危险的,
因为该空间可能已另分配,所以必须妥善保存new返回的指针,以保证不发生内存泄漏,也必须保证不会重复释放堆内存空间。
4.动态分配的变量或对象的生命期。无名对象的生命期并不依赖于建立它的作用域,
比如在函数中建立的动态对象在函数返回后仍可使用。我们也称堆空间为自由空间(free store)就是这个原因。
但必须记住释放该对象所占堆空间,并只能释放一次,在函数内建立,而在函数外释放是一件很容易失控的事,往往会出错。