当前位置: 首页 > news >正文

C++ 分配内存 new/malloc 区别

C++ 分配内存 new/malloc 区别

  • 1. new/malloc 设计目的
  • 2. new/malloc 内存分配与释放机制
  • 3. new/malloc 应用场景对比
    • 3.1 new/delete典型应用场景
      • 场景 1:动态创建类对象
      • 场景 2:动态创建多态对象(基类指针指向派生类)
      • 场景 3:创建带资源的对象(RAII)
      • 场景 4:自定义内存管理(重载 operator new/delete)
      • 场景 5:配合智能指针使用(推荐现代 C++)
    • 3.2 malloc/free典型应用场景
      • 场景 1:与 C 库或系统 API 交互
      • 场景 2:分配原始字节缓冲区
      • 场景 3:C 风格结构体数组或 POD 类型(Plain Old Data)
      • 场景 4:自定义内存池 / 分配器底层实现
      • 场景 5:与 C 语言共享数据
  • 4. 现代 C++ 替代方案

1. new/malloc 设计目的

new/malloc 简介

🔹new/delete 管“对象”;需要构造/析构;
🔹malloc/free 管“内存”;按字节分配和释放内存块,而不是对象

new/malloc 设计目的

项目new/deletemalloc/free
所属语言C++ 关键字(语言内建)C 标准库函数<cstdlib>
设计目的面向对象内存管理 —— 创建/销毁“对象”原始内存管理 —— 分配/释放“字节块”
核心理念调用构造/析构函数、类型安全、异常安全仅操作内存,不关心类型或对象生命周期
是否可重载✅ 可重载 operator new/delete❌ 不可

2. new/malloc 内存分配与释放机制

特性new/deletemalloc/free
分配方式在堆上为对象分配内存在堆上分配指定字节的内存
调用构造函数✅ 自动调用❌ 不会调用
调用析构函数delete 自动调用❌ 不会调用
返回类型对象的类型指针(自动转换)void*(需手动强制类型转换)
内存不足时抛出 std::bad_alloc 异常返回 nullptr
释放方式deletedelete[]free
可混用❌ 严禁混用❌ 严禁混用

📘 示例对比:

// new/delete
MyClass* obj = new MyClass(10);
delete obj;// malloc/free
MyClass* obj2 = (MyClass*)malloc(sizeof(MyClass));
// ⚠️ 构造函数不会被调用
free(obj2);

3. new/malloc 应用场景对比

场景类型推荐方式理由
动态创建 C++ 对象new/delete自动调用构造与析构
复杂类、多态体系结构new/delete保证虚析构安全
与 C 接口交互malloc/freeC 接口不识别 C++ 对象语义
原始字节缓冲区(图像、网络包)malloc/free不需要构造函数,灵活
C 风格结构体数组(POD 类型)malloc/free无对象语义即可
RAII / 智能指针管理对象std::make_unique / std::make_shared安全、自动释放
内存池 / 分配器实现malloc/free 或重载 operator new可控、高性能
STL 容器管理对象容器内部 new/delete 自动管理不需手动分配

3.1 new/delete典型应用场景

场景 1:动态创建类对象

当对象大小或数量在运行时才确定时,用 new 创建。

// 编译时不知道要多少个点
int n;
std::cin >> n;
Point* points = new Point[n];   // 调用 n 次构造函数
// ...
delete[] points;                // 调用 n 次析构函数

📌 特点:

  • 支持任意复杂构造(含参数)。
  • 自动调用析构函数释放资源。
  • 推荐用在动态生命周期对象。

场景 2:动态创建多态对象(基类指针指向派生类)

new 能确保正确调用构造/析构链,是面向对象编程的常见做法。

Base* obj = new Derived(); // 调用 Derived 构造
// ...
delete obj; // 调用 Derived + Base 析构

📌 关键点:

  • 析构函数必须是 虚函数(virtual ~Base())。
  • 用 malloc 无法触发这些行为,会造成资源泄露或未定义行为。

场景 3:创建带资源的对象(RAII)

new 是 RAII 模式的基础:对象管理资源,生命周期自动控制。

std::ofstream* f = new std::ofstream("data.txt");
// 析构时自动关闭文件
delete f;

📘 RAII(Resource Acquisition Is Initialization)强调:

  • 构造 → 获取资源,析构 → 释放资源。
  • malloc 不能实现这种模式。

场景 4:自定义内存管理(重载 operator new/delete)

在性能关键或嵌入式系统中,可能要控制内存分配策略。

void* MyClass::operator new(size_t size) {return MyMemoryPool::Allocate(size);
}
void MyClass::operator delete(void* p) {MyMemoryPool::Free(p);
}

📌 可用于:

  • 内存池 / 对象池;
  • 高性能游戏引擎;
  • 实时系统。

场景 5:配合智能指针使用(推荐现代 C++)

现代 C++ 几乎不直接 delete 对象,而是用智能指针管理。

auto p = std::make_unique<MyClass>();   // 内部调用 new
auto q = std::make_shared<MyClass>();   // 自动引用计数

📘 优点:

  • 自动释放;
  • 避免内存泄漏;
  • 异常安全。

3.2 malloc/free典型应用场景

场景 1:与 C 库或系统 API 交互

如果你在 C++ 程序中调用 纯 C 接口,或者 系统 API(如 Windows / POSIX 函数),这些接口通常要求使用 malloc/free。

// C 库函数接口
void* buffer = malloc(1024);  
read(fd, buffer, 1024);
process_data((unsigned char*)buffer);
free(buffer);

📘 原因:
C 接口不知道 C++ 的 new 机制,也不会调用构造/析构。使用 malloc/free 可保证兼容性。

场景 2:分配原始字节缓冲区

当你只需要“字节空间”,不需要“对象语义”时,malloc 非常合适。

void* data = malloc(width * height * 3);  // 分配图像缓冲区
memset(data, 0, width * height * 3);
free(data);

📌 典型用途:

  • 图像、音频、网络包、二进制数据缓冲;
  • 临时缓存;
  • 原始内存池。

场景 3:C 风格结构体数组或 POD 类型(Plain Old Data)

对于无构造函数/析构函数的简单结构体,malloc 足够用。

struct Point { float x, y, z; };Point* pts = (Point*)malloc(100 * sizeof(Point));
for (int i = 0; i < 100; i++) {pts[i].x = pts[i].y = pts[i].z = 0;
}
free(pts);

📘 注意:
如果结构体有构造函数(哪怕是隐式的),必须用 new,否则构造函数不会执行。

场景 4:自定义内存池 / 分配器底层实现

即使在现代 C++ 中,很多高性能容器(如 std::pmr、游戏引擎、数据库缓存)底层仍使用 malloc/free 或 aligned_alloc 实现。

void* block = malloc(blockSize);
MemoryPool::Add(block);

📘 用途:

  • 控制分配策略;
  • 避免频繁系统调用;
  • 做对象池、缓冲池、环形队列等。

场景 5:与 C 语言共享数据

当 C++ 模块需要和 C 模块共享数据结构时,内存必须由 C 可识别的方式分配。

extern "C" void c_function(void* buf);void* buf = malloc(256);
c_function(buf);
free(buf);

4. 现代 C++ 替代方案

目标推荐替代原因
动态数组std::vector<T>自动释放,支持对象语义
单个堆对象std::unique_ptr<T> / std::make_unique<T>无需手动 delete
引用计数对象std::shared_ptr<T> / std::make_shared<T>自动管理生命周期
临时缓冲区std::vector<uint8_t> / std::byte安全且类型明确
多线程内存管理自定义内存池 + operator new 重载控制分配策略与性能
http://www.dtcms.com/a/503460.html

相关文章:

  • Respective英文单词学习
  • 网络排错全流程:从DNS解析到防火墙,逐层拆解常见问题
  • 移动端开发工具集锦
  • 使用Nvidia Video Codec(三) NvDecoder
  • 周口规划建设局网站wordpress模板中添加短代码
  • Linux小课堂: 命令手册系统深度解析之掌握 man 与 apropos 的核心技术机制
  • 阿里云做网站官网网站改版的seo注意事项
  • 每日算法刷题Day76:10.19:leetcode 二叉树12道题,用时3h
  • 【OS笔记11】:进程和线程9-死锁及其概念
  • 贪心算法1
  • 服务器搭建vllm框架并部署模型+cursor使用经验
  • Arduino采集温湿度、光照数据
  • 32HAL——外部中断
  • 网站建设会议议程新闻营销发稿平台
  • 【图像处理】CMKY色彩空间
  • 南宁建行 网站南通网站的优化
  • 构建AI智能体:六十八、集成学习:从三个臭皮匠到AI集体智慧的深度解析
  • 从入门到精通【Redis】Redis 典型应⽤ --- 分布式锁
  • 6.5 万维网(答案见原书P294)
  • CycloneDDS:跨主机多进程通信全解析
  • Java基础语法—类型转换、表达式的自动类型提升
  • CentOS8无法使用sudo提权
  • 软件工程师招聘信息网站数据库对网站开发的作用
  • Python核心数据结构与函数编程
  • Spring Boot 3零基础教程,WEB 开发 内容协商 接口返回 YAML 格式的数据 笔记35
  • 网站编程学北京上海网站建设公司
  • 查询土耳其公司商业登记册(工商报告),可以获取什么信息?
  • ip反查域名
  • 把AI“撒”进农田:基于极值量化与状态机的1KB边缘灌溉决策树
  • 代码随想录 404.左叶子之和