~动态内存管理~

来源:互联网 发布:通话数据统计软件 编辑:程序博客网 时间:2024/06/05 11:30
C语言动态内存管理
1.C语言使用malloc/calloc/realloc/free进行动态内存管理。
2.malloc/calloc/realloc
  malloc函数原型: void *malloc(size_t size);  //分配内存块(不会抛出异常)
            功能: 在内存的动态存储区中分配一个size字节大小的内存块,返回一个指向该块开头的指针。若size的大小为0,则返回值取决于特定的库实现,但返回的指针不应被解除引用。
                   新分配的内存块内容不被初始化。
          返回值: 申请成功时,返回指向由该功能分配的内存块的指针;申请失败时,返回空指针。

  calloc函数原型: void *calloc(size_t num, size_t size);  //分配并初始化内存块(不会抛出异常)
            功能: calloc函数与malloc函数相似,不同的是calloc函数会将分配的内存块初始化为0。若size的大小为0,则返回值取决于特定的库实现,但返回的指针不应被解除引用。
          返回值: 申请成功时,返回指向由该功能分配的内存块的指针;申请失败时,返回空指针。

  realloc函数原型:void *realloc(void *ptr, size_t size);  //重新分配内存块(不会抛出异常)
             功能:更改ptr指向内存块的大小(将内存块移动到新位置)。即使将内存块移动到新位置,内存块的内容仍可保留到新旧内存的较小者。若是新的内存块较大,则新分配的部分内存值是不确定的。
                   在ptr为空指针的情况下,函数的功能就如同malloc。
                   (C90/C98)若size的值为0,则先前在ptr中分配的内存被解除分配,就像调用free函数,并返回一个空指针。
                   (C99/C11)若size的大小为0,则返回值取决于特定的库实现,但返回的指针不应被解除引用。
           返回值:返回指向重新分配的内存块的指针,可能与ptr相同或者新位置。
3.free
  free函数原型:void free(void *ptr);  //释放分配内存块(不会抛出异常 )
          功能:释放分配给malloc、calloc、realloc的内存块,使其再次可用于进一步分配。此函数不会更改ptr本身的值,因此ptr仍指向相同的位置(已无效)。
                若ptr未指向由malloc、calloc、realloc申请的的内存块,则会导致未定义的行为。若ptr为空指针,则该函数不执行任何操作。

C++动态内存管理
1.C++通过new和delete动态管理内存。
  new/delete动态管理对象,new[]/delete[]动态管理对象数组。
  注意:malloc/free、new/delete、new[]/delete[]一定要匹配使用,否则可能出现内存泄露甚至崩溃的问题.
2.全局变量、全局静态变量、局部变量、局部静态变量之间的区别是什么?
  1)全局变量、全局静态变量、局部静态变量存储在数据段上,局部变量存储在栈上。
  2)字符串存储在代码段上,malloc/calloc/realloc/new申请的内存块(并非内存块的名称)存储在堆上。
  3)栈又叫堆栈,存储非静态局部变量/函数参数/函数返回值等等,且栈是下增长的。
  4)内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可以使用系统接口创建共享内存,作进程间通信。
  5)堆存储程序运行时动态内存分配,且堆是向上增长的。
  6)数据段存储全局数据和静态数据。
  7)代码段存储可执行代码/只读常量。
3.我们知道C++是兼容C的,那么已经有C库malloc/free等来动态管理内存,为什么C++还要定义new/delete运算符来动态管理内存?(malloc/free和new/delete的区别与联系)
  1)malloc/free和new/delete都是动态管理内存的入口。
  2)malloc/free是C/C++标准库的函数,new/delete是C++操作符。
  3)malloc/free只是动态分配内存空间/释放空间,new/delete除了分配/释放内存还会调用构造函数和析构函数进行初始化与清理工作。
  4)malloc/free需要手动计算类型大小且返回值为void *,new/delete可自己计算类型的大小且返回值为对应类型的指针。
4.C++其他内存管理接口  (并没有重载new/delete表达式)
  void *operator new(size_t size);
  void operator delete(size_t size);
  void *operator new[](size_t size);
  void operator delete[](size_t size);
  通过调用operator new函数执行new表达式获得内存,接着在该函数中构造一个对象。
  通过撤销一个对象执行delete表达式,接着调用operator delete函数释放对象使用的内存。
  总结:1)operator new、operator delete、operator new[]、operator delete[]与malloc/free用法一样。
        2)只负责分配/释放空间,不会调用对象构造/析构函数来初始化/清理对象。
        3)实际上operator new、operator delete只是malloc、free的一层封装。
5.执行的操作
  1)new做了两件事
     调用operator new分配空间、调用构造函数初始化对象
  2)delete做了两件事
     调用析构函数清理对象、调用operator delete释放空间
  3)new[N]做了两件事  (分配空间时会在空间的开始处多分配4个字节的大小,用于存储N,便于析构)
     调用operator new分配空间、调用N次构造函数分别初始化每个对象
  4)delete[N]做了两件事
     调用N次析构函数清理对象、调用operator delete释放空间
6.定位new表达式
  定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
  new(place_address) type                    (place_address必须是一个指针)
  new(place_address) type(initializer_list)  (initializer_list是类型的初始化列表)
  1)malloc/free + 定位操作符new()/显示调用析构函数,模拟new/delete行为
     类名 *p = (类名 *)malloc(sizeof(类名));
     new(p) 类名(初始值);  //new
     p->类名的析构函数;
     free(p);  //delete
  2)malloc/free + 多次调用定位操作符new()/显示调用析构函数,模拟new[]/delete[]行为
     类名 *p = (类名 *)malloc(sizeof(类名)* N);
     for(i=0;i<N;i++)
     {
          new(p+i) 类名;
     }  //new[N]
     for(i=0;i<N;i++)
     {
          p[i].类名的析构函数;
     }
     free(p);  //delete[N]
7.深度剖析new/delete与new[]/delete[]
  1)new(size) -> operator new() -> malloc() -> 构造函数 -> ptr(返回值)
     delete(ptr) -> 析构函数 -> operator delete() -> free()
  2)new[count](size+4) -> operator new[]() -> operator new() -> malloc() -> 构造函数(count次) -> ptr(返回值)
     delete[] -> 析构函数(count次) -> operator delete[]() -> operator delete() ->free()
     (new type[] type显示定义析构函数才会多开4个字节,以存储对象个数
原创粉丝点击