经典之辩——malloc和new

引子:

1、存储分配:

(1)通常定义变量(或对象),编译器在编译时都可以根据该变量(或对象)的类型知道所需内存空间的大小,从而系统在适当的时候为他们分配确定的存储空间。这种内存分配称为静态存储分配

(2)有些操作对象只在程序运行时才能确定,这样编译时就无法为他们预定存储空间,只能在程序运行时,系统根据运行时的要求进行内存分配(堆中的内存空间),这种方法称为动态存储分配

2、内存区域:

(1)全局代码区:从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

(2)堆内存(heap):亦称动态内存。如malloc和new申请的内存空间,要用指针访问,没有先后顺序。动态内存的生存期由程序员自己决定,需要手动释放内存,使用非常灵活。

(3)栈内存(stack):依附于线程,先进后出,存储局部数据。如存放函数的参数值、函数变量的值等,自动分配。生存期完结自动回收。

工作机制:(引自百度百科)

操作系统将可用的内存块连接为一个长长的列表的所谓空闲链表

申请动态内存时,沿连接表寻找一个大到足以满足用户请求所需要的内存块。

然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。

释放动态内存时,它将用户释放的内存块连接到空闲链上。


1、malloc函数

函数原型:void *malloc(unsigned int num_bytes);

是什么:malloc的全称是memory allocation,中文叫动态内存分配。

干什么:

用于申请一块连续的指定大小的内存块区域,以void*类型返回分配的内存区域地址。

如果申请不成功,返回NULL。

其中,C++规定,void* 类型可以通过类型转换强制转换为任何其它类型的指针。

怎么用:

#include<iostream>
#include<stdlib.h>  //包含malloc()函数的头文件,不可省略.h,这是一个C的头文件
using namespace std;
void main()
{
   char *p=(char*)malloc(sizeof(char) * 5);  //申请了5个连续的字符型空间,也就是5*1个byte。
   
 if(p!=NULL) //如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。)
 {
  ......
 }
 else
 {
    printf("mallocerror!\n");
    exit(-1);  
 }
 free(p);   //当内存不再使用时,用free()函数将此内存返还给系统
 p=NULL;
}

  使用注意

  (1)malloc函数要求必须要由我们计算字节数,作为参数传递给malloc函数。如上例中的参数sizeof(char)*5。

  (2)在返回给某个指针时,由于malloc函数返回的是void*类型的指针,所以需要强制转换类型。如上例中的(char*)。          对于C++,如果你写成:

char *p=malloc(sizeof(char) * 5);
          则程序无法通过编译,报错:“不能将 void* 赋值给 int * 类型变量”。

  (3)malloc一般与free函数配对使用,否则易造成内存泄漏。

     而且free函数调用以后,内存空间虽然已经归还,但是指针仍然指向原地址。

  (4)malloc不会自动初始化内存空间,里面是随机值。

*calloc函数

函数原型:void *calloc(size_t n, size_t size);
功 能:在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。
与malloc区别calloc在动态分配完内存后,自动初始化该内存空间为零。
释放空间:使用free(起始地址的指针) 对内存进行释放。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
 
void main()
{
    char *str;
 
    /*分配内存空间*/
    str = (char*)calloc(10,sizeof(char));
 
    /*将hello写入*/
    strcpy(str, "Hello");
 
    /*显示变量内容*/
    printf("String is %s\n",str);
 
    /*释放空间*/
    free(str);
}

2、new运算

是什么:是个封装好的运算符,不是函数,因此不需要库的支持。

干什么:用于申请堆中分配的存贮空间

怎么用:

(1)指针变量名 = new 类型名(初始化式);(申请一个内存空间)

int *p=new int(5);//申请一个int空间,初始化为5
delete p;

      (2)指针变量名 = new  类型名[个数];(申请一堆连续的动态内存空间)

int* p=new int[5];//申请5个连续的int型内存
delete []p;

  使用注意:

(1)自动计算需要分配的空间,返回的是个指向所分配类型变量(对象)的指针

(2)初始化规律:对于有构造函数的类,不论有没有括号,都用构造函数进行初始化;如果没有构造函数,则不加括号的new只分配内存空间,不进行内存的初始化,而在末尾加了括号的new会在分配内存的同时初始化为0。

(3)delete通常与new配对使用。

   delete p;释放了指针p所指的目标的内存空间,但指针p本身并没有撤销,它自己仍然存在,该指针仍然指向原地址。

(4)指针p存于栈中,p所指向的内存空间是在堆中。

(5)在c++中与malloc的最大区别:

  对于类的对象,通过new建立的对象要调用构造函数,通过deletee删除对象也要调用析构函数。
  

最后之总结 
 
1、malloc和free,new和delete,都是配对使用。
  同时,在C++中,两组之间不能混着用,虽说有时能编译过,但容易存在较大的隐患。

2、malloc和free属于C语言中的函数,需要库的支持,而new/delete是C++中的运算符,所以new/delete的执行效率高些。C++中为了兼用C语法,所以保留malloc和free的使用,但建议尽量使用new和delete。

3、new类型安全,返回的是某种数据类型的指针,malloc非类型安全,返回的是void指针。

int* p = malloc(sizeof(char )*10);    // 编译时无法指出错误

free (p);    //只释放内存的头指针
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值