C++的malloc、calloc、realloc和new的区别

    我猜你一看到这个题目就晕了,这是什么鬼~~

    哈哈哈哈, 其实这四个东西正是C++提供的动态内存分配的四种方法,但你会问 “为什么要这么多种方法呢?一种方法不香吗?搞这么多种,太复杂了,呜呜呜~~”。你会这么想那说明你是正常人,说实话小编刚开始也是这么想的,但是有一天,小编在工作中终于被逼上梁山,无奈将这几个东西给整理了一遍。今天就将笔记无偿送给各位亲爱的你们。

    好了,进入正题。

    我们都知道在工程的开发中,有些时候你真的不知道一个数组究竟要设置多大的空间合适,像定义了一个存放身份证号码的数组:

unsigned long int ID[size]

这个数组用来存放国民的身份证,但是人口数量是不断变化的,不断增长,你不知道这个size要设置多大,10000?1000000000?设小了,那人口要是多于这个数那就空间不足了,设大了,那人口的数量要是远远小于这个数值,那么就会造成内存空间的浪费。所以呢,为了解决这个问题,C++给我们提供了动态分配的功能,也就是向内存申请一个连续的空间,这个空间可以根据size去确定,或者可以在空间快满的时候,使用reacolloc申请更大的内存空间。

    三种动态申请内存空间的函数如下:   

    void* malloc(unsigned int size);

    void* realloc(void *ptr, unsigned int newsize);

    void* calloc(size_t numElements, size_t sizeOfElement);

    加上一种new关键字,这四个都可以用来向内存申请空间。

malloc:

malloc(unsigned int size),它可以在内存的堆(Heap)区域申请连续大小为size个字节的空间,然后成功的话返回void*指针(C/C++中,void*可以被强制转换为其他类型的指针,像int*等等),这个指针是申请这段连续空间的首地址,如果申请失败的话就返回NULL指针。

void Malloc_Test(){
  char* ptr = (char*)malloc(10);                  // 向内存堆申请10个char类型的连续空间,并且返回首地址
  cout<<"malloc申请到的空间首地址时:"<<&ptr<<endl;
  strcpy(ptr,"Serven");                          // 如果你复制strcpy(ptr,"Servenssssssssssssssssssss");c程序就会中断,因为你申请的区域不够放了
  cout<<"malloc申请到的空间赋值的字符串:"<<ptr<<endl<<endl;
  free(ptr);
​
}

运行结果:

calloc:

calloc(unsigned int n, unsigned int size),它可以在内存的堆(Heap)区域申请连续n个空间,每个空间包含了size个字节的大小,也就是总共向内存申请了n*size个字节的空间大小,然后成功的话返回void*指针(这列的也是可以被强制转换的),这个指针是申请这段连续空间的首地址,如果申请失败的话就返回NULL指针。

void Calloc_Test(){
​
  char* ptr = (char*) calloc(10,sizeof(char));          // 通过calloc申请10个char类型大小的内存空间
  cout<<"calloc申请到的空间首地址时:"<<&ptr<<endl;  
  strcpy(ptr,"Serven");
  cout<<"calloc申请到的空间赋值的字符串:"<<ptr<<endl<<endl;
  free(ptr);
}
​

运行结果:

realloc:

realloc(void *ptr, unsigned int newsize),这个的作用是向内存申请一个newsize的空间大小。当使用malloc申请的内存不够用的时候,就是用realloc来进行申请更大的空间,前面的指针ptr就是一开始用malloc申请所返回的指针。realloc申请的方式是从内存堆的开始地址高地址查找一块区域,这块区域大于newsize的大小,申请成功后将原本的数据从开始到结束一起拷贝到新分配的内存区域,然后将原本malloc申请的区域释放掉(注意的是:原来的指针是自动释放的,不需要使用free来进行释放)。最后再这块区域的首地址返回。当内存不再使用时,要记得用free()函数进行释放。

void Realloc_Test(){
​
  char *ptr = (char*)malloc(5*sizeof(char));
  strcpy(ptr,"Serven");
  cout<<"malloc申请到的空间首地址时:"<<&ptr<<endl;
  cout<<"malloc申请到的空间赋值的字符串:"<<ptr<<endl;
​
  char *ptru = (char*)realloc(ptr, 10 * sizeof(char));      // 通过realloc扩大ptr的空间,并把新的地址赋值给ptru,原来的ptr指针会自动释放的,不用再free了,不然会出现Debug error问题
  strcpy(ptru,"Hello, Serven");
  cout<<"realloc申请到的空间首地址时:"<<&ptru<<endl;
  cout<<"realloc申请到的空间赋值的字符串:"<<ptru<<endl<<endl;
​
  //free(ptr);                // 这里千万不用释放,因为realloc在帮你申请新的内存区域后会将ptr释放掉
  //free(ptru);                // 按道理这列是要释放掉的,但是问我释放的时候出问题了,有小伙伴知道是啥原因留个言
}
运行结果:

new 关键字

new是C++提供的关键字,也是操作符,我们可以使用new在内存的堆上创建一个对象,在创建对象的时候,new其实做了以下的操作:在堆上获得一块内存空间->调用构造函数(创建建档的类型变量时除外)->返回正确的指针

    char* p = new char(‘e’):分配1个char类型大小的内存空间;

    char* p = new char[5]:   分配5个char类型大小的内存空间。

void New_Test(){
  char* ptr = new char('e');          // 开辟一个存放数组的存储空间,返回一个指向该存储空间的地址,相当于ptr[0] = 'e'
  char* ptru = new char[5];
  ptru[0] = ptru[1] = ptru[2] = ptru[3] = ptru[4] = '5';
  cout<<ptr[0]<<endl;
  cout<<ptru[0]<<' '<<ptru[1]<<' '<<ptru[2]<<' '<<ptru[3]<<' '<<ptru[4]<<' '<<endl;
​
​
  delete ptr;
  delete ptru;
​
}

运行结果:

比较:

函数申请区域申请长度返回指针初始化?头文件
mallocsizevoid*

不初始化

(会出现垃圾数据)

<stdlib.h>/<malloc.h>
callocn*sizevoid*

初始化

(保证数据都是0)

<stdlib.h>/<malloc.h>
reallocnewsizevoid*

  • 如果申请调用成功,malloc()和calloc()函数都会返回所分配的内存空间的首地址;

  • free()释放函数时紧跟着malloc、calloc、realloc,因为它们都是返回void*;而new使用的时delete;

  • malloc和calloc之间的区别就是:malloc申请成功后没有初始化,这样会导致一些垃圾数据的存在,calloc会初始化,将申请到的这一段连续空间初始化为0,如果是实型数据的话,则会初始化为浮点数的0;

  • malloc、calloc、realloc三者都是返回void*,C/C++支持强制转换void*成其他类型的指针;

  • malloc是在动态存储区域申请分配一块长度为size字节的连续区域,并返回这块区域的首地址;calloc是在动态存储区域申请分配n块长度为size字节的区域,并返回这块区域的首地址;realloc是将ptr内存大小增大到newsize个字节;

  • realloc是从堆上分配内存,在扩大空间的时候会直接在现存的数据后面获得附加的字节,如果空间能够满足的话就扩展,如果不满足的话,那就从堆的开始地址开始寻找,找到第一个足够大的自由块,然后将现有的数据拷贝到新的位置,而老的那一块还是放到堆上。

欢迎大家关注小编的公众号 “三贝勒文子”呀~~​,每天更新关于C++和C的知识点。

  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三贝勒文子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值