C++ new/delete和malloc/free的区别(面试总结)

打印 上一主题 下一主题

主题 1713|帖子 1713|积分 5139

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x

性质

malloc/free 是C语言中的标准库函数,用于动态内存管理;
new/delete 是C++中的操作符,底层调用了 malloc/free。

分配方式

malloc、free
  1. int* arr = (int*)malloc(10 * sizeof(int)); // 分配
  2. free(arr); // 释放
复制代码
代码含义:


  • 动态分配了一块连续内存,用于存储10个 int 范例的整数;
  • 10 * sizeof(int):分配巨细为 10 * 4 ( int范例字节数) = 40字节;
  • (int*)malloc : malloc返回范例是void*,通过(int*)逼迫转换成int*范例指针;
  • free(arr): 释放malloc分配的内存,arr变成悬空指针,释放后的内存不可以再访问。
new、delete
  1. int* val = new int(42);    // 分配并初始化
  2. delete val;                // 释放
复制代码
代码含义:


  • new int(42):主动计算范例巨细(不必要sizeof),分配巨细为 42 * 4 = 168字节;
  • 返回 int*范例的指针;
特性malloc/freenew/delete范例安全返回void*,需逼迫转换返回该范例对象的指针内存巨细手动计算主动分配
内存区域

malloc函数从堆上分配内存,而new在自由存储区(free store)上分配内存。
无论是使用 ​​malloc​ 还是 ​​new​​,内存分配初始都在​​虚拟内存上​​,​​物理内存的分配是延迟的​​(由操作体系的​​按需分页机制​​控制)


  • 如果直接使用物理内存,内存管理会变得复杂低效;
  • 虚拟内存是操作体系为每个进程提供的抽象内存空间,独立于物理内存,进程看到的地点是虚拟地点,必要通过硬件和页表来转换为物理地点;
    1.每个进程拥有独立的虚拟地点空间,互不干扰,
    2.虚拟地点空间连续,物理内存是可以离散的,
    3.通过分页和交换技术,虚拟内存可以大于物理内存,
    4.物理内存分配是延迟的,只有当程序首次访问这块内存,内核才会分配物理内存。
  • malloc 和 new ​​只操作虚拟内存​​,物理内存的分配由操作体系在​​首次访问内存时,通过缺页异常触发。​​
malloc 举动
仅分配虚拟内存,不触发物理内存分配,首次访问内存(写入或读取)时才分配物理内存。
  1. int* arr = (int*)malloc(1024 * sizeof(int));  // 仅虚拟内存分配
  2. arr[0] = 10;  // 首次写入触发缺页异常,分配物理内存
复制代码
new 举动
为对象分配虚拟内存地点,并调用构造函数,构造函数初始化内容可能隐含首次内存访问,从而间接触发物理分配。
  1. class MyClass {
  2. public:
  3.     int data;
  4.     MyClass() { data = 42; }  // 写入data操作触发缺页异常,分配物理内存
  5. };
  6. MyClass* obj = new MyClass(); // 物理内存在构造函数执行时分配
复制代码
  1. class MyClass {
  2. public:
  3.     int data;  // 未初始化
  4.     MyClass() {}  // 无内存访问
  5. };
  6. MyClass* obj = new MyClass(); // 物理内存未分配,直到后续访问obj->data
复制代码

底层实现

malloc/free
仅管理内存,不涉及构造/析构函数的调用
分配空间重要有两种方式(brk,mmap)


  • 小内存分配(通常小于128KB):
    在堆上分配虚拟连续的内存区域,释放时,内存块被标志为空闲,并不会立刻归还给操作体系,而是加入空闲链表(供后续 malloc 重用),分配速度快,但是会导致内存碎片化。
  • ​大内存分配​(大于128KB):
    使用 mmap 直接在进程的虚拟地点空间中常见独立的内存映射,释放时整个映射区立即归还给体系,避免了碎片化,但是开销比力大。
new/delete
new 和 delete 都是 C++ 的关键字,new 的举动分为 内存分配 和 对象构造 两部,delete 的举动分为 ​对象析构​​ 和 ​​内存释放​​ 两步。
new:
1.operate new(起首调用全局的 operator new 函数分配内存,默认实现基于 malloc);
2.申请充足的空间;
3.调用构造函数,初始化变量。
delete:
1.调用析构函数;
2.operate delete(默认实现调用 free);
3.释放空间。

失败处置惩罚

malloc 在内存分配失败时返回 NULL,需手动查抄返回值。
必须显式查抄返回值,并且无异常机制,完全依赖流程控制。
new 在内存分配失败时抛出异常(std::bad_alloc)​​
异常机制主动流传错误,适合面向对象和复杂场景,如果构造函数抛出异常,已分配的内存会被主动释放。

重载能力

malloc/free 是C语言标准库的预定义函数,在链接时绑定到标准库实现,没法通过语言特性直接替换它们。
new/delete 可以通过重载 operator new 和 operator delete 来自定义动态内存分配和释放的举动。
  1. class MyClass {
  2. public:
  3.     // 重载类的数组 new[]
  4.     static void* operator new[](size_t size) {
  5.         std::cout << "类内 new[]: 分配数组 " << size << " 字节\n";
  6.         void* p = malloc(size);
  7.         if (!p) throw std::bad_alloc();
  8.         return p;
  9.     }
  10.     // 重载类的数组 delete[]
  11.     static void operator delete[](void* p) noexcept {
  12.         std::cout << "类内 delete[]: 释放数组内存\n";
  13.         free(p);
  14.     }
  15. };
  16. int main() {
  17.     MyClass* arr = new MyClass[5]; // 触发类的 operator new[]
  18.     delete[] arr;                  // 触发类的 operator delete[]
  19.     return 0;
  20. }
复制代码

小结

本文重要从分配方式、内存存储、失败处置惩罚以及重载能力几个方面介绍了 malloc/free 和 new/delete 的区别,希望能对你有资助!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

风雨同行

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表