C/C++内存管理

这里写目录标题

C语言中动态内存管理

C语言中动态内存管理方式:malloc/calloc/realloc/free

特性 malloc calloc realloc
核心功能 基础分配 分配并初始化为 0 调整已分配内存的大小
函数参数 1个(总字节数) 2个(元素个数, 单个元素大小) 2个(原内存指针, 新字节数)
内存初始化 不初始化,内存里是随机的垃圾值 自动清零,所有位初始化为 0 保留原有数据,新扩容部分不初始化
典型用途 追求高性能,或后续会立刻赋值的场景 分配数组、结构体,或需要"干净"内存的场景 动态数组扩容、缩容

当然,realloc的开辟方法有点特殊

情况一:原地扩容(运气好)

情况二:异地搬迁(你说的"新找一个空间")

void Test ()

{

// 1.malloc/calloc/realloc的区别是什么?

int* p2 = (int*)calloc(4, sizeof (int));

int* p3 = (int*)realloc(p2, sizeof(int)*10);

// 这里需要free(p2)吗?

free(p3 );

}

注:不需要free掉p2了,因为realloc在调用的时候就已经把p2给释放掉了

代码

javascript 复制代码
#include <stdio.h>
#include <stdlib.h>

int main() {
    int *arr = NULL;

    // ==========================================
    // 1. malloc:只分配空间,不初始化(里面是随机的垃圾值)
    // ==========================================
    printf("--- 1. 测试 malloc ---\n");
    // 申请 5 个 int 的空间
    arr = (int*)malloc(5 * sizeof(int));
    if (arr == NULL) return 1; // 必须检查内存是否分配成功

    printf("malloc 申请 5 个空间后的初始值(通常是乱码/垃圾值):\n");
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n\n");

    // 用完记得释放,方便后面演示 calloc
    free(arr);
    arr = NULL;

    // ==========================================
    // 2. calloc:分配空间,并自动将所有位初始化为 0
    // ==========================================
    printf("--- 2. 测试 calloc ---\n");
    // 申请 5 个 int 的空间,参数是 (元素个数, 单个元素大小)
    arr = (int*)calloc(5, sizeof(int));
    if (arr == NULL) return 1;

    printf("calloc 申请 5 个空间后的初始值(自动清零):\n");
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n\n");

    // ==========================================
    // 3. realloc:调整已分配内存的大小(扩容/缩容)
    // ==========================================
    printf("--- 3. 测试 realloc ---\n");
    // 现在想把数组从 5 个 int 扩容到 10 个 int
    // 注意:必须用临时指针接收 realloc 的返回值,防止失败导致原指针丢失
    int *temp = (int*)realloc(arr, 10 * sizeof(int));
    if (temp == NULL) {
        free(arr); // 扩容失败也要释放原来的内存
        return 1;
    }
    arr = temp; // 扩容成功,更新指针

    printf("realloc 扩容到 10 个空间后的值:\n");
    printf("前 5 个是原来 calloc 留下的 0,后 5 个是新增的(通常是垃圾值):\n");
    for (int i = 0; i < 10; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    // ==========================================
    // 程序结束,统一释放内存
    // ==========================================
    free(arr);
    arr = NULL;

    return 0;
}

C++内存管理方式

通过new和delete操作符进行动态内存管理。

代码

javascript 复制代码
void Test()
{
// 动态申请一个int类型的空间
int* ptr4 = new int;
// 动态申请一个int类型的空间并初始化为10
int* ptr5 = new int(10);
// 动态申请3个int类型的空间
int* ptr6 = new int[3];
int* ptr10 = new int[10]{1, 2, 3}; // 申请 10 个 int 的数组并初始化
delete ptr4;
delete ptr5;
delete[] ptr6;
delete[] ptr10;
}

单个对象:用 new 申请,必须用 delete 释放。

连续空间(数组):用 new\[\] 申请,必须用 delete\[\] 释放。

核心原则:申请时用了方括号 \[\],释放时就必须带上 \[\];申请时没带,释放时也不能带。

两者区别

在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。

代码体现

javascript 复制代码
#include <iostream>
#include <cstdlib> // malloc 和 free 需要的头文件
using namespace std;

class Student {
public:
    // 构造函数
    Student(int id = 0) : _id(id) {
        cout << "【构造函数】被调用!学生ID: " << _id << endl;
    }
    // 析构函数
    ~Student() {
        cout << "【析构函数】被调用!学生ID: " << _id << " 正在释放资源..." << endl;
    }

private:
    int _id;
};

int main() {
    cout << "------ 1. 测试 malloc 和 free (C语言风格) ------" << endl;
    // malloc 只管开辟空间,不会调用构造函数
    Student* s1 = (Student*)malloc(sizeof(Student)); 
    cout << "malloc 开辟空间完毕(注意:上面没有打印构造函数)\n" << endl;
    
    // free 只管释放空间,不会调用析构函数
    free(s1);
    cout << "free 释放空间完毕(注意:上面也没有打印析构函数)\n\n" << endl;


    cout << "------ 2. 测试 new 和 delete (C++风格) ------" << endl;
    // new 开辟空间的同时,会自动调用构造函数
    Student* s2 = new Student(1001);
    cout << "new 开辟空间完毕(注意:上面自动打印了构造函数)\n" << endl;

    // delete 释放空间前,会自动调用析构函数
    delete s2;
    cout << "delete 释放空间完毕(注意:上面自动打印了析构函数)" << endl;

    return 0;
}

new

new干了两件事

1.开辟对象的空间

2.调用构造函数

delete

delete干了两件事

1.先调用析构函数

2.把p1指向的空间释放

相关推荐
lingran__7 小时前
C++_stack和queue和priority_queue(容器适配器)
开发语言·c++
小保CPP7 小时前
OpenCV C++基于极值区域滤波算法的场景文本检测(OCR)
c++·人工智能·opencv·算法·计算机视觉·ocr
::呵呵哒::7 小时前
java中SseEmitter
java·开发语言
星恒随风7 小时前
C++ 多态底层原理:静态绑定、动态绑定、虚函数表与工程实践
开发语言·c++·笔记·学习
wuyk5558 小时前
68.嵌入式 C 语言避坑指南:volatile 关键字 —— 单片机中断、寄存器访问的核心技巧
c语言·开发语言·stm32·单片机·嵌入式硬件
qz_Serene8 小时前
C语言:编译和链接
c语言·开发语言
会编程的土豆8 小时前
功能详解 01 · 用户注册:从表单到数据库一行
开发语言·数据库·后端·mysql·golang
白色冰激凌8 小时前
[SECS/GEM研究] (四)HSMS 用TCP取代串口
网络·c++·网络协议·secs/gem
Ivanqhz8 小时前
Rust collect() 浅析
开发语言·后端·rust
Wang's Blog8 小时前
Go-Zero项目开发33: IM实时通信前后端对接与微服务基础设施实践
开发语言·微服务·golang·go-zero