动态内存分配

目录

1. C语言

1.1 malloc

1.2 calloc

1.3 realloc

2. C++

2.1 new的原理

4.2 delete的原理

4.3 delete[] 如何知道释放内存的大小


1. C语言

头文件

#include <stdlib.h>

1.1 malloc

函数功能:

分配所需的内存空间,并返回一个指向它的指针。

void *malloc(size_t size) 

参数:

size--内存块的大小,以字节为单位。

返回值:

该函数返回一个指针 ,指向已分配大小的内存。如果请求失败,则返回 NULL。

示例:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
int main()
{
   char *str = (char*)malloc(15);
   strcpy(str, "runoob");
   printf("String = %s,  Address = %u\n", str, str);
   free(str);
   return(0);
}

1.2 calloc

函数功能:

分配所需的内存空间,并返回一个指向它的指针。

malloc和calloc之间的不同点是:malloc 不会设置内存为零,而 calloc 会设置分配的内存为零。

函数原型:

void *calloc(size_t nitems, size_t size)

函数参数:

nitems -- 要被分配的元素个数。

size -- 元素的大小。

返回值:

该函数返回一个指针,指向已分配的内存首地址。如果请求失败,则返回 NULL。

示例:

#include <stdio.h>
#include <stdlib.h>
 
int main()
{
   int i, n;
   int *a;
 
   printf("要输入的元素个数:");
   scanf("%d",&n);
 
   a = (int*)calloc(n, sizeof(int));
   printf("输入 %d 个数字:\n",n);
   for(i = 0 ; i < n ; i++) 
   {
      scanf("%d",&a[i]);
   }
 
   printf("输入的数字为:");
   for( i=0 ; i < n ; i++ ) 
   {
      printf("%d ",a[i]);
   }
   free (a);  // 释放内存
   return(0);
}

1.3 realloc

函数功能:

尝试重新调整之前调用 malloc 或 calloc 所分配的 ptr 所指向的内存块的大小。

realloc 函数可以根据实际需要,对当前使用的内存大小进行调整。

函数原型:

void *realloc(void *ptr, size_t size)

函数参数:

ptr -- 指针指向一个要重新分配内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。
        如果为NULL,则会分配一个新的内存块,且函数返回一个指向它的指针。此时realloc等同于malloc函数
size -- 内存块的新的大小,以字节为单位。
        如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被释放,并返回一个空指针。

返回值:

该函数返回一个指针 ,指向重新分配大小的内存。如果请求失败,则返回 NULL。

示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
   char *str;
 
   /* 最初的内存分配 */
   str = (char*) malloc(15);
   strcpy(str, "runoob");
   printf("String = %s,  Address = %p\n", str, str);
 
   /* 重新分配内存 */
   str = (char*)realloc(str, 25);
   strcat(str, ".com");
   printf("String = %s,  Address = %p\n", str, str);
 
   free(str);
   
   return(0);
}

执行结果:

String = runoob,  Address = 0x7fa2f8c02b10
String = runoob.com,  Address = 0x7fa2f8c02b10

从执行结果可以看出,使用realloc分配的地址只是改变了地址空间的大小,其地址没有发生变化

补充说明:

如果要申请更大的内存,realloc函数内部要分两种情况进行处理:

  • 情况1:原有内存后面有足够的空闲内存空间可用,那么扩展内存时会在原有内存之后直接追加空间,原来内存中的数据不发生变化。
  • 情况2:原有内存后面没有足够大的内存空间可用,这时 realloc 函数会在堆空间上另找一个合适大小的连续空间来使用,函数返回这个新的内存地址;并且realloc 函数会将原来内存中的数据自动拷贝到新的内存空间中。

2. C++

new和delete

2.1 new的原理

new对象:

  • 对于简单类型,直接调用operator new分配内存;
  • 对于复杂结构,先调用operator new分配内存,然后在分配的内存上调用构造函数;

new数组:

  • 对于简单类型,new[]计算好大小后调用operator new;
  • 对于复杂数据结构,new[]先调用operator new[]分配内存,然后在p的前四个字节写入数组大小n,然后调用n次构造函数
    • 即:针对复杂类型,new[]会额外存储数组大小。假设指针p指向new[]分配的内存,因为要4字节存储数组大小,实际分配的内存地址为[p-4],系统记录的也是这个地址

4.2 delete的原理

delete对象:

  • 对于简单类型,默认只是调用free函数
  • 对于复杂类型,先调用析构函数,再调用operator delete

delete数组:

  • 对于简单类型,delete和delete[]相同
  • 假设指针p指向new[]分配的内存,因为要4字节存储数组大小,实际分配的内存地址为[p-4],系统记录的也是这个地址。delete[]实际释放的就是p-4指向的内存。而delete会直接释放p指向的内存,这个内存根本没有被系统记录,所以会崩溃。

4.3 delete[] 如何知道释放内存的大小

需要在 new [] 一个对象数组时,需要保存数组的维度,C++ 的做法是在分配数组空间时多分配了 4 个字节的大小,专门保存数组的大小,在 delete [] 时就可以取出这个保存的数,就知道了需要调用析构函数多少次了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值