静态方法:变量所占的内存空间不需要程序员自己管理,编译器在编译阶段自动将管理这些空间的代码加入到目标文件中,程序运行时,由操作系统自动为变量分配内存单元,在变量的生存期内,变量一直占用内存单元,在生存期结束后自动释放内存单元。特点是大小固定,不能扩展。
问题:有些程序必须在运行时才能确定需要多少内存空间来存储数据...
解决:使用动态分配内存方法。
动态分配内存:程序运行时根据当前指令随时为存储数据分配内存空间,完全由程序员自己进行内存的分配和释放。在堆里面进行分配。
C语言:malloc()和free()对
C++语言:new()和delete()对
new用法:new运算返回所分配内存单元的起始地址,所以需要把返回值保存在一个指针变量中。若分配不成功,返回NULL,并抛出异常。
<指针变量> = new <数据类型>
<指针变量> = new <数据类型> [整型表达式]
<指针变量> = new <数据类型>(<初始值>) 【PS这里应该是对象构造函数的方式,比如 int (10), string(10,'9'), 如果是自己定义的结构体或者类类型,按照定义的构造方法来初始化 】
例:
int *p1 = new int;
float *p2 = new float;
char *pBuffer = new char[100];
int *pA = new int[size];
student *stu = new student[num];
int *pNum = new int(100);
要注意的是,new没有为创建的对象命名,只能通过指针去访问对象或者数组。
delete <指针变量>
delete []<动态分配的数组名>
例:
delete pNum;
delete []pBuffer;
PS: new和delete必须配对使用。虽然程序结束后系统会自动释放程序和其中数据所占的内存空间,但是为了在程序运行过程中能够重复使用有限的内存资源,防止系统产生内存泄漏,还是应该即时释放不需要的动态分配的内存单元,以便系统能随时对该内存单元进行分配。
delete只是释放内存,销毁内存上的对象,但是指针还是还存在的,并且仍然指向原来的内存,也就是指针的值还是内存的地址。指针是一个变量,只有程序结束时才被销毁。只不过现在指针指向的内容是是未定义的,所以说是垃圾【所谓的迷途指针】。所以释放内存后把指针指向NULL,也就是不指向任何内存,防止指针在后面不小心又被解引用了从而引发问题。
malloc/free VS new/delete
new运算不需要进行强制类型转换,使用简单方便;
new运算是通过调用构造函数初始化动态创建的对象,执行效率更高;
使用new能够进行异常处理,使用更安全。
更详细的区别见另一篇博客:malloc和new区别
需要注意的问题:
1. 如果你在函数上面定义了一个指针变量,然后在这个函数里申请了一块动态分配的内存让指针指向它。实际上,这个指针的地址是在栈上,但是它所指向的内容却是在堆上面。这一点要注意!所以,在一个函数里申请了空间后,比如:
// code...
void Function(void)
{
char *p = (char *)malloc(100 * sizeof(char));
}
千万不要认为函数返回,函数所在的栈被销毁指针也跟着销毁,申请的内存也就一样跟着销毁了。这是错误的。因为申请的内存在堆上,除非程序员手动释放,否则要等到程序结束释放所有内存才会释放它们,跟函数是否结束没有关系。也就是函数所在的栈被销毁跟堆完全没有关系。所以,忠告就是:使用完不再需要记得释放动态分配的内存!在该部分程序退出之前释放内存并立即给P赋0值(NULL)。另一个办法是保证P在没有初始化之前,将不再被使用。