首页 > 代码库 > 内存管理函数

内存管理函数

1 calloc函数

【函数原型】:void* calloc (size_t num, size_t size);

【功能】:  在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0;

【返回值】: 分配成功返回指向该内存的地址,失败则返回 NULL;

【头文件】: #include <stdlib.h>


如果 size 的值为 0,那么返回值会因标准库实现的不同而不同,可能是 NULL,也可能不是,但返回的指针不应该再次被引用。

注意:函数的返回值类型是 void *,void 并不是说没有返回值或者返回空指针,而是返回的指针类型未知。所以在使用 calloc() 时通常需要进行强制类型转换,将 void 指针转换成我们希望的类型,例如:

char *ptr = (char *)calloc(10, 10); // 分配100个字节的内存空间


calloc() 与 malloc()的一个重要区别是:

  calloc() 在动态分配完内存后,自动初始化该内存空间为零,而 malloc() 不初始化,里边数据是未知的垃圾数据。

下面的两种写法是等价的:

  // calloc() 分配内存空间并初始化

char *str1 = (char *)calloc(10, 2);

 

  // malloc() 分配内存空间并用 memset() 初始化

char *str2 = (char *)malloc(20);

if(str2 )

{

memset(str2, 0, 20);

}

 

 

2 malloc()函数

【函数原型】:   void * malloc(int size);

【功能】:          分配大小为size的内存;

【返回值】:    分配成功返回指向该内存的地址,失败则返回 NULL;

【头文件】:    #include <stdlib.h>

 

malloc()函数分配内存但不初始化,需要用memset函数初始化

void * memset (void * p,int c,int n) ;

 

 

3 realloc()函数

【函数原型】:   void * realloc(void * p, int size);

【功能】:          分配大小为size的内存;

【返回值】:    分配成功返回指向该内存的地址,失败则返回 NULL;

【头文件】:    #include <stdlib.h>

 

realloc函数将指针 p指向的内存块的大小改变为n字节。如果n小于或等于p之前指向的空间大小,会有数据丢失。如果n大于原来p之前指向的空间大小,那么,系统将重新为p从堆上分配一块大小为n的内存空间,同时,将原来指向空间的内容依次复制到新的内存空间上,p之前指向的空间被释放。relloc函数分配的空间也是未初始化的。

relloc()并不保证调整后的内存空间和原来的内存空间保持同一内存地址,相反,relloc返回的指针很可能指向一个新地址。所以在代码中,我们必须将relloc的返回值,重新赋值给p : p=(int *) relloc (p, sizeof(int)*15);

 

 

4 free()函数

【函数原型】:   void free (void * p);

【功能】:          释放指针p指向的内存;

【返回值】:    无

【头文件】:    #include <stdlib.h>

 

对于malloc(), realloc(), calloc()申请的内存,在free()后还需要置NULL;free函数只是释放指针指向的内容,而该指针仍然指向原来指向的地方,此时,指针为野指针,如果此时操作该指针会导致不可预期的错误。安全做法是:在使用free函数释放指针指向的空间之后,将指针的值置为NULL

 

 

5 new/delete

实例:
        Obj *objects = new Obj[100];
        delete []objects;

操作时发生事件:

 new的时候会有两个事件发生:

1).内存被分配(通过operator new 函数) 

2).为被分配的内存调用一个或多个构造函数构建对象

delete的时候,也有两件事发生:

1).为将被释放的内存调用一个或多个析构函数 

 2).释放内存(通过operator delete 函数)

特殊应用:

   使用delete是未加括号,delete便假设删除对象是单一对象。否则便假设删除对象是个数组。因此,如果在调用new时使用了[],则在调用delete时也使用[],如果你在调用new的时候没有[],那么也不应该在调用时使用[]。

 

malloc/free new/delete 的本质区别:

1.malloc/free是C/C++语言的标准库函数,new/delete是C++的运算符

2.new能够自动分配空间大小

3.对于用户自定义的对象而言,用maloc/free无法满足动态管理对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++需要一个能对对象完成动态内存分配和初始化工作的运算符new,以及一个能对对象完成清理与释放内存工作的运算符delete---简而言之 new/delete能进行对对象进行构造和析构函数的调用进而对内存进行更加详细的工作,而malloc/free不能。

既然new/delete的功能完全覆盖了malloc/free,为什么C++还保留malloc/free呢?因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。所以new/delete,malloc/free必须配对使用。

 

 

 

 

 

 

内存管理函数