C/C++ 动态内存管理

为什么要动态内存管理?

在我们写程序前不确定要多大的内存时,或者当开静态空间开大了浪费,开小了不够用的情况。使用动态内存管理能更加灵活,可以按需调整内存大小。

动态内存的存储位置:

动态内存存储在堆区(Heap),这个区域由我们程序员来进行内存空间的申请和释放。

动态分配内存的函数(C语言)malloc、calloc、realloc、free 包含在头文件:stdlib.h

C++提供了新的操作符来方便我们操作

先介绍C语言动态管理内存的方式:

1、malloc和free

1、malloc :

语法形式:

void* malloc(size_t size);

这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。

  1. 如果开辟成功,则返回一个指向开辟好空间的指针
  2. 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要检查
  3. 返回值的类型是void*,所以malloc函数并不知道开辟空间的类型,具体在使用的时候由使用者自己决定
  4. 如果参数size为0,malloc的行为是标准未定义的,取决于编译器

2、free:

free是专门用来做动态内存的释放和回收的

语法形式:

void free(void* ptr);
  1. 如果参数ptr指向的空间不是动态开辟的,那free函数的行为是未定义的
  2. 如果参数ptr是NULL指针,则函数什么都不做

比如:

#include<stdio.h>
#include<stdlib.h>

int main()
{
    int num = 0;
    scanf("%d",&num);
    int arr[num] = {0};
    int* ptr = NULL;
    ptr = (int*)malloc(num*sizeof(int));//向内存申请空间
    if(ptr == NULL)//申请失败就返回
    {
        return 1;
    }
    else
    {
        int i = 0;
        for(i=0;i<num;i++)
        {
            *(ptr + i) = 0;
        }
    }

    free(ptr);//释放ptr所指向的动态内存
    ptr = NULL;

    return 0;
}

2、calloc和realloc

这俩也用来分配动态内存

1、calloc:

语法形式:

void* calloc(size_t num,size_t size);
  1. 函数的功能是为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0
  2. 与函数malloc的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为0

比如:

2、realloc:

语法形式:

void* realloc(void* ptr,size_t size);

realloc函数可以对动态开辟内存的大小进行调整。

  1. ptr是要调整的内存地址
  2. size调整之后的大小
  3. 返回值为调整之后的内存起始位置
  4. 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间
  5. realloc在调整内存空间的时候存在两种情况:

             情况一:原有空间之后有足够大的空间

             情况二:原有空间之后没有足够大的空间

当是情况一时,要扩展内存就直接在原内存之后直接追加空间,原来空间的数据不发生变化。

当是情况二时,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用,这样函数返回的是一个新的内存地址。

#include <stdio.h>
#include <stdlib.h>

int main() 
{
    int *ptr;
    int n, i;

    // 初始分配内存,存储5个整数
    n = 5;
    ptr = (int*)malloc(n * sizeof(int));
    if (ptr == NULL) 
    {
        printf("内存分配失败!\n");
        return 1;
    }

    // 给数组赋值
    for (i = 0; i < n; i++) 
    {
        ptr[i] = i + 1;
    }

    // 打印初始数组
    printf("初始数组:");
    for (i = 0; i < n; i++) 
    {
        printf("%d ", ptr[i]);
    }
    printf("\n");

    // 重新分配内存,扩展到10个整数
    n = 10;
    ptr = (int*)realloc(ptr, n * sizeof(int));
    if (ptr == NULL) 
    {
        printf("内存重新分配失败!\n");
        free(ptr); // 释放内存
        return 1;
    }

    // 给新分配的空间赋值
    for (i = 5; i < n; i++) 
    {
        ptr[i] = i + 1;
    }

    // 打印扩展后的数组
    printf("扩展后的数组:");
    for (i = 0; i < n; i++) 
    {
        printf("%d ", ptr[i]);
    }
    printf("\n");

    // 释放内存
    free(ptr);
    return 0;
}

开动态内存注意(易错点):

  1. 忘记检查内存分配是否成功
  2. 忘记释放内存导致内存泄漏(动态分配的内存需要手动释放。如果忘记释放,程序运行时会占用越来越多的内存,最终可能导致系统资源耗尽)
  3. 重复释放同一块空间
  4. 访问已经释放的内存(野指针)

3、c++内存管理方式

因为C++兼容C语言,所以C语言里进行动态内存管理的函数在C++也能用。不过C++提供了更加方便的操作符newdelete。

3.1、new、delete操作内置类型

void Test()
{
    // 动态申请一个int类型的空间
    int* ptr4 = new int;
 
    // 动态申请一个int类型的空间并初始化为10
    int* ptr5 = new int(10);
 
    // 动态申请10个int类型的空间
    int* ptr6 = new int[10];
 
    delete ptr4;
    delete ptr5;
    delete[] ptr6;
}

注意:new和delete,new[]和delete[]匹配起来使用

3.2、操作自定义类型

跟C语言不同的点在于,C++在new时会调用构造函数,在delete释放空间前会先调用析构函数

C++内存申请失败时,会抛异常。


malloc/free和new/delete区别:

malloc/free和new/delete的共同点是:都是从上申请空间,并且需要用户手动释放。不同的地方是:

  1. malloc和free是函数,new和delete是操作符
  2. malloc申请的空间不会初始化,new可以初始化
  3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可, 如果是多个 对象,[]中指定对象个数即可
  4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
  5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间 后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值