C++ 中自主内存管理 new/delete 与 malloc/free 完全详解

C++ 中 new/delete 与 malloc/free 完全详解


一、new/delete 与 malloc/free 的区别

特性 new/delete malloc/free
属于 C++语言 C语言
申请的内存区 堆(Heap) 堆(Heap)
返回类型 指向对象类型的指针(自动转换) void*,需手动强制转换类型
是否调用构造函数 是(调用构造函数) 否(只分配内存,不调用构造函数)
是否调用析构函数 是(调用析构函数) 否
申请失败 抛出异常(std::bad_alloc) 返回 NULL

二、详细解释

1. malloc/free(C语言风格)

  • malloc(size_t size):申请一块连续的内存区域,大小为 size 字节。
  • 返回 void*,需要强制类型转换成需要的指针类型。
  • 不会调用对象的构造函数,只是单纯分配内存。
  • free(void* ptr):释放由 malloc 分配的内存,不调用析构函数。

使用场景:

  • 兼容 C 的项目
  • 只需要原始内存、不需要对象初始化时

2. new/delete(C++风格)

  • new Type(args):分配内存 + 调用构造函数。
  • delete ptr:调用析构函数 + 释放内存。
  • 可以分配单个对象,也可以分配数组对象(new Type[n])。

使用场景:

  • 需要构造和析构管理的 C++ 对象
  • 更安全、更易用,符合 C++ RAII 风格

三、常见使用示例

1. malloc/free 示例

cpp 复制代码
#include <cstdlib>  // for malloc/free
#include <iostream>

struct MyStruct {
    int x;
    float y;
};

int main() {
    // malloc 分配内存
    MyStruct* p = (MyStruct*)malloc(sizeof(MyStruct));
    if (p == nullptr) {
        std::cerr << "Memory allocation failed!" << std::endl;
        return 1;
    }

    // 手动初始化
    p->x = 10;
    p->y = 3.14f;

    std::cout << "x = " << p->x << ", y = " << p->y << std::endl;

    // free 释放内存
    free(p);

    return 0;
}

2. new/delete 示例

cpp 复制代码
#include <iostream>

struct MyStruct {
    int x;
    float y;

    // 构造函数
    MyStruct(int a, float b) : x(a), y(b) {
        std::cout << "Constructor called!" << std::endl;
    }

    // 析构函数
    ~MyStruct() {
        std::cout << "Destructor called!" << std::endl;
    }
};

int main() {
    // new 分配并调用构造函数
    MyStruct* p = new MyStruct(10, 3.14f);

    std::cout << "x = " << p->x << ", y = " << p->y << std::endl;

    // delete 调用析构函数并释放
    delete p;

    return 0;
}

3. new/delete\[\](数组版本)

cpp 复制代码
#include <iostream>

int main() {
    // 分配一个数组
    int* arr = new int[5];

    for (int i = 0; i < 5; ++i)
        arr[i] = i * 10;

    for (int i = 0; i < 5; ++i)
        std::cout << arr[i] << " ";
    std::cout << std::endl;

    // 必须使用 delete[] !!!
    delete[] arr;

    return 0;
}

四、注意事项总结(超级重要)

项目 说明
1 new 和 delete 要成对使用
2 new[] 和 delete[] 要成对使用 (不是 delete!!!)
3 不要混用 malloc 和 delete,或 new 和 free (严重错误!)
4 避免内存泄漏:申请的内存必须释放,否则内存泄漏
5 申请后立即检查返回值 :malloc 返回 NULL,new 可以捕捉异常
6 构造/析构问题 :malloc 不负责对象构造,new 是
7 自定义 new/delete :可以通过重载 operator new / operator delete 控制内存分配策略(如内存池优化)
8 异常安全 :尽量使用智能指针(如 std::unique_ptr、std::shared_ptr)避免手动管理内存错误

五、常见错误示例

cpp 复制代码
// 错误示例1:malloc分配,用delete释放
int* p = (int*)malloc(sizeof(int));
delete p;  // ❌ 错,应使用 free(p);

// 错误示例2:new分配,用free释放
int* q = new int(5);
free(q);  // ❌ 错,应使用 delete q;

// 错误示例3:new[]配delete
int* arr = new int[10];
delete arr;  // ❌ 错,应使用 delete[] arr;

小结

malloc/free new/delete
只分配/释放内存,不调用构造析构函数 分配内存并调用构造/析构函数
返回 void* 返回对应类型的指针
C 风格 C++ 风格
适合简单内存申请(不需要对象管理) 适合对象创建与销毁(有构造析构过程)
相关推荐
蜗牛一步步往上爬2 小时前
第十六章 C++语言在深度学习中的应用
开发语言·c++·深度学习
艺杯羹2 小时前
Windows原生软件锁设计:从暴力杀进程丢数据到零轮询事件驱动架构
windows·系统架构·开源·开源软件·内存管理·开源协议
Navigator_Z5 小时前
LeetCode //C - 1317. Convert Integer to the Sum of Two No-Zero Integers
c语言·算法·leetcode
wo_jack5 小时前
C++ 入门笔记(十六):第16课 vector 模拟实现十问十答 —— 从三指针到迭代器失效
c++·后端·面试·stl·vector
D e re k ZH6 小时前
C++ 标准库算法全景指南
数据结构·c++·算法
冻柠檬飞冰走茶6 小时前
字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)
c语言·开发语言·数据结构·算法·动态规划
雪落漂泊7 小时前
C++算法 二分查找篇(上)
开发语言·c++·算法
不会算法的笨小孩8 小时前
异常的使用以及会出现的问题
开发语言·c++·c++11·异常
LabVIEW开发9 小时前
LabVIEW 连接板:28 个端子怎么排,优先级怎么定
java·算法·labview