C++内存分配与释放
通常定义变量或者对象,编译器在编译时都可以根据该变量或对象的类型知道所需内存空间的大小,从而系统在适当的时候为他们分配确定的存储空间,这种内存分配被称为静态存储分配。
有些操作对象只有在程序运行时才能确定,这样编译器在编译时就无法为他们预定存储空间,只能在程序运行时,系统根据运行时的要求进行内存分配,这种方法称为动态内存分配。
所有动态存储分配都在堆区中进行。
内存的分配与释放
当程序运行到需要一个动态分配的变量或对象,必须向系统申请取得堆中的一块所需大小的存储空间,用于存储该变量或对象。当不再使用该变量或对象时,也就是它生命结束之时,要显式释放它所占用的存储空间,这样系统就能对该堆空间进行再分配,做到重复使用有限资源。
在C++中,申请和释放堆中分配的存储空间,分别使用new和delete的两个运算符来完成,使用格式如下:
指针变量名 = new 类型名(初始化式)
delete指针名
new运算符返回的是一个指向所分配类型变量(对象)的指针。对所创建的变量或对象,都是通过该指针来间接操作的,而动态创建的对象本身没有名字。
#include<iostream> using namespace std; class ST { private: int a; public: ST(int _a=0):a(_a) { this->a = _a; cout<<"Object was built. "<<endl; } ~ST() { cout<<"Object was free. "<<endl; } }; void malloc_free() { ST *tmp = (ST*)malloc(sizeof(ST)); free(tmp); } void new_delete() { ST *tmp = new ST[1];//但是new为对象数组分配空间不可初始化 delete []tmp; } void main() { ST *pt = new ST(1);//new为对象分配空间就可初始化 delete [] pt;//delete p 是删除pt所指空间,而并非删除pt,为了预防野指针可将pt=NUll malloc_free(); new_delete(); }
运行结果
malloc&free,new&delete都是申请释放空间,但是,有如下几点不同
1.new申请时不需要强制转换类型,也不需要申请结束后判断是否申请到(因为其内部含有未申请到异常退出)
2.new在为某个对象申请空间时,会调用构造函数,因此可在申请时初始化(对象的构造函数要支持),delete也会在释放空间时会先调用析构函数
3.由堆区创建对象数组(例如ST*pt = new ST[10]),只能调用缺省的构造函数(缺省构造函数:不含参数的或每个参数都有默认值的构造函数),不能调用其他任何构 造函数。若没有缺省的构造函数则不能创建对象数组。还有,创建对象数组时不可以初始化。
4.对数组进行动态分配格式如下:
指针变量名 = new 类型名[下标表达式]
(下标表达式不是常量表达式,可不必再编译时确定)
delete []指向该数组的指针变量名
这两者必须搭配使用,若delete未加[],编译器会认为该指针是指向数组的第一个元素的指针,仅仅回收第一个元素所占空间。加上[]则会回收整个数组。