《分配空间和删除空间》由会员分享,可在线阅读,更多相关《分配空间和删除空间(4页珍藏版)》请在金锄头文库上搜索。
1、void *malloc(long NumBytes):该函数分配了 NumBytes 个字节,并返回了指向这块内存的 指针。如果分配失败,则返回一个空指针(NULL) 。 关于分配失败的原因,应该有多种,比如说空间不足就是一种。void free(void *FirstByte): 该函数是将之前用 malloc 分配的空间还给程序或者是操作系统, 也就是释放了这块内存,让它重新得到自由。补充补充 NULL: char * p = NULL;指针变量为空值, 即该指针变量不指向任何变量; 事实上 NULL 是整数 0,它使 p 的存储单元中所有二进位均为 0,也就是使 p 指向地址为 0 的
2、 单元.系统保证使该单元不作它用(不存放有效数据),即有效数据的指针不指向 0 单元。实际 上先宣言 NULL,即 #define NULL 0 p = NULL注意:p 的值为 NULL 与未对 p 赋值是两个不同的概念。前者是有值的(0) ,不指向任何变 量,而未对 p 赋值并不等于 p 无值,只是它的值是一个不确定的值,也就是 p 实际上可能 指向一个事先未指定的单元。这种情况危险的。因此,在引用指针变量之前应对它赋值。注意事项:注意事项: A、申请了内存空间后,必须检查是否分配成功。 B、当不需要再使用申请的内存时,记得释放;释放后应该把指向这块内存的指针指向 NULL,防止程序后面不
3、小心使用了它。 C、这两个函数应该是配对。如果申请后不释放就是内存泄露;如果无故释放那就是什么也 没有做。释放只能一次,如果释放两次及两次以上会出现错误(释放空指针例外,释放空 指针其实也等于啥也没做,所以释放空指针释放多少次都没有问题) 。 D、虽然 malloc()函数的类型是(void *),任何类型的指针都可以转换成(void *),但是最好还是 在前面进行强制类型转换,因为这样可以躲过一些编译器的检查。堆:堆:堆是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆 就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统 要额外的堆,但是记得
4、用完了要还给操作系统,要不然就是内存泄漏。栈:栈:栈是线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化, 每个线程的栈互相独立。每个函数都有自己的栈,栈被用来在函数之间传递参数。操作系 统在切换线程的时候会自动的切换栈,就是切换 SS/ESP 寄存器。栈空间不需要在高级语言 里面显式的分配和释放。栈栈是由编译器自动分配释放,存放函数的参数值、局部变量的值等。操作方式类似于数据 结构中的栈。 堆堆一般由程序员分配释放,若不释放,程序结束时可能由 OS 回收。注意这里说是可能, 并非一定。所以我想再强调一次,记得要释放!free()释放的是指针指向的内存!注意!释放的是内存,不
5、是指针!这点非常非常重要!指针是一个变量,只有程序结束时才被销毁。释放了内存空间后,原来指向这块空间的指针 还是存在!只不过现在指针指向的内容的垃圾,是未定义的,所以说是垃圾。因此,前面 我已经说过了,释放内存后把指针指向 NULL,防止指针在后面不小心又被解引用了。非常 重要啊这一点!有了有了 malloc/free 为什么还要为什么还要 new/delete ?malloc 与 free 是 C+/C 语言的标准库函数标准库函数,new/delete 是 C+的运算符运算符。它们都可用于申申 请动态内存和释放内存。请动态内存和释放内存。 对于非内部数据类型的对象而言,光用对于非内部数据类型
6、的对象而言,光用 malloc/free 无法满足动态对象的要求。对象在创建无法满足动态对象的要求。对象在创建 的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于 malloc/free 是库是库 函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务 强加于强加于 malloc/free。 因此因此 C+语言需要一个能完成动态内存分配和初始化工作的运算符语言需要一个能完成动态内存分配和初始化工作的运算符 new,以
7、及一个能完成,以及一个能完成 清理与释放内存工作的运算符清理与释放内存工作的运算符 delete。 注意注意 new/delete 不是库函数。不是库函数。#include using namespace std; class Obj public:Obj();Obj();void Initialize();void Destroy(); ; Obj:Obj() coutInitialize();a-Destroy();free(a);/new 和和 delete运算符运算符 Obj *b=new Obj;delete b; system(“pause“);return 0; 类类 Obj 的
8、函数的函数 Initialize 模拟了构造函数的功能,函数模拟了构造函数的功能,函数 Destroy 模拟了析构函数的功能。函模拟了析构函数的功能。函 数数 UseMallocFree 中,由于中,由于 malloc/free 不能执行构造函数与析构函数,必须调用成员函数不能执行构造函数与析构函数,必须调用成员函数 Initialize 和和 Destroy 来完成初始化与清除工作。函数来完成初始化与清除工作。函数 UseNewDelete 则简单得多。则简单得多。 所以我们不要企图用所以我们不要企图用 malloc/free 来完成动态对象的内存管理,应该用来完成动态对象的内存管理,应该用
9、 new/delete。由于内。由于内 部数据类型的部数据类型的“对象对象”没有构造与析构的过程,对它们而言没有构造与析构的过程,对它们而言 malloc/free 和和 new/delete 是是 等价的。等价的。 既然既然 new/delete 的功能完全覆盖了的功能完全覆盖了 malloc/free,为什么,为什么 C+不把不把 malloc/free 淘汰出局呢?淘汰出局呢? 这是因为这是因为 C+程序经常要调用程序经常要调用 C 函数,而函数,而 C 程序只能用程序只能用 malloc/free 管理动态内存。管理动态内存。 如果用如果用 free 释放释放“new 创建的动态对象创
10、建的动态对象” ,那么该对象因无法执行析构函数而可能导致程,那么该对象因无法执行析构函数而可能导致程 序出错。如果用序出错。如果用 delete 释放释放“malloc 申请的动态内存申请的动态内存” ,理论上讲程序不会出错,但是该,理论上讲程序不会出错,但是该 程序的可读性很差。所以程序的可读性很差。所以 new/delete 必须配对使用,必须配对使用,malloc/free 也一样。也一样。内存分配的使用:内存分配的使用: 1 建议建议 new,delete,而不是,而不是 malloc,free 2 new 要判断返回值,经常成功不代表一定成功要判断返回值,经常成功不代表一定成功 3
11、delete 指针后尽量赋值指针后尽量赋值 NULL我们先看一下下面的这段程序,有这么一个程序段:我们先看一下下面的这段程序,有这么一个程序段:class Apublic:A() cout“A is here!“endl; A() cout“A is dead!“endl; private:int i;A* pA=new A;delete pA;实际上,这段程序里面隐含调用了一些我们没有看到的东西,实际上,这段程序里面隐含调用了一些我们没有看到的东西, 在这个简单的程序段里面,在这个简单的程序段里面, new/delete 究竟做了些什么?那就是:究竟做了些什么?那就是:static void
12、* operator new(size_t sz); static void operator delete(void* p);这就是这就是 new 可以申请很多种类型变量空间的原因。可以申请很多种类型变量空间的原因。 new A;实际上做了实际上做了 2 件事:调用件事:调用 opeator new,在自由存储区分配一个,在自由存储区分配一个 sizeof(A)大小的内存大小的内存 空间;然后调用构造函数空间;然后调用构造函数 A()。 ,在这块内存空间上类砖砌瓦,建造起我们的对象。同样对,在这块内存空间上类砖砌瓦,建造起我们的对象。同样对 于于 delete,则做了相反的两件事:调用析构函
13、数,则做了相反的两件事:调用析构函数A(),销毁对象,调用,销毁对象,调用 operator delete,释,释 放内存。放内存。 运算符运算符 new 和和 delete 提供了存储的动态分配和释放功能。它的作用相当于提供了存储的动态分配和释放功能。它的作用相当于 C 语言的函数语言的函数 malloc()和()和 free()() ,但是性能更为优越。使用,但是性能更为优越。使用 new 比使用比使用 malloc()有以下的几个优点:()有以下的几个优点:1、new 自动计算要分配类型的大小,不使用自动计算要分配类型的大小,不使用 sizeof 运算符,比较省事,可以避免错误。运算符,比较省事,可以避免错误。 2、它自动地返回正确的指针类型,不用进行强制指针类型转换。、它自动地返回正确的指针类型,不用进行强制指针类型转换。 3、可以用、可以用 new 对分配的对象进行初始化。对分配的对象进行初始化。 不过需要注意的是,不过需要注意的是,new 分配一块内存的时候,并没有对这块内存空间清零或者初始化。分配一块内存的时候,并没有对这块内存空间清零或者初始化。