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

new/delete 和 malloc/free 区别

new/deletemalloc/free 最根本的区别在于:
new/delete 是 C++ 的运算符,而 malloc/free 是 C 语言的标准库函数。这个根本差异导致了它们在行为和使用上的一系列重要区别。

下面我们从多个维度进行详细对比。


核心差异总结表

特性new / deletemalloc() / free()
语言C++ 运算符C 库函数 (<cstdlib>)
内存来源自由存储区 (Free Store) (Heap)
构造函数/析构函数会调用不会调用
返回值类型返回确切类型指针 (如 MyClass*)返回 void* (需要强制转换)
分配失败行为抛出 std::bad_alloc 异常返回 NULL
计算内存大小编译器自动计算程序员手动计算 (使用 sizeof)
重载可以为自定义类重载不可以重载
初始化可使用 new Type() 进行值初始化只能分配未初始化的内存
数组处理有专门的 new[]delete[]需要手动计算数组大小,统一用 free 释放
类型安全类型安全类型不安全 (需要 void* 转换)

详细分解与示例

1. 构造与析构的调用 (最关键的差异)

这是两者最本质的区别,直接关系到 C++ 的对象生命周期管理。

  • new

    1. 分配足够大小的内存。

    2. 调用类的构造函数在该内存上初始化对象。

  • delete

    1. 调用类的析构函数清理对象管理的资源。

    2. 释放该对象所占用的内存。

  • malloc仅仅分配一块指定大小的原始内存,不会调用构造函数。你得到的是一个“空壳”。

  • free仅仅释放之前分配的内存块,不会调用析构函数。如果对象内部管理着资源(如动态内存、文件句柄),会导致资源泄漏

示例

cpp

class MyClass {
public:MyClass()  { std::cout << "Constructor called\n"; data = new int[100]; }~MyClass() { std::cout << "Destructor called\n"; delete[] data; }
private:int* data;
};int main() {// 使用 new/deleteMyClass* obj1 = new MyClass; // 输出: Constructor calleddelete obj1;                 // 输出: Destructor called (资源被正确清理)// 使用 malloc/freeMyClass* obj2 = (MyClass*)malloc(sizeof(MyClass)); // 只分配内存,无输出// obj2 指向的内存是未初始化的,访问其成员是未定义行为free(obj2); // 只释放内存,无输出。~MyClass() 未被调用,导致 data 指向的 100 个 int 内存泄漏!return 0;
}
2. 返回类型与类型安全
  • new:返回的是与所分配类型严格匹配的指针(例如 new int 返回 int*)。这是类型安全的。

  • malloc:返回的是 void*,必须由程序员进行强制类型转换才能使用。如果转换错误,编译器可能无法发现,这是类型不安全的。

示例

cpp

// new - 类型安全
int* p1 = new int; // 正确
// double* p2 = new int; // 错误:无法从 int* 转换到 double*// malloc - 类型不安全
int* p3 = (int*)malloc(sizeof(int)); // 需要强制转换,容易写错
double* p4 = (double*)malloc(sizeof(int)); // 编译通过,但逻辑错误!运行时行为未定义。
3. 分配失败的处理
  • new:在内存分配失败时,默认会抛出 std::bad_alloc 异常。你可以使用 std::nothrow 版本来让其返回 nullptr

    cpp

  • try {int* p = new int[10000000000LL]; // 可能分配失败
    } catch (const std::bad_alloc& e) {std::cerr << "Memory allocation failed: " << e.what() << '\n';
    }// 使用 nothrow 版本
    int* p = new (std::nothrow) int[10000000000LL];
    if (p == nullptr) {// 处理分配失败
    }
  • malloc:在内存分配失败时,直接返回 NULL(或 nullptr in C++11+)。你需要检查返回值。

    cpp

  • int* p = (int*)malloc(10000000000LL * sizeof(int));
    if (p == NULL) {// 处理分配失败
    }
4. 内存大小计算
  • new编译器自动计算所需内存的大小。你只需要指定类型,不需要 sizeof

  • malloc程序员必须手动计算所需内存的字节数,使用 sizeof 运算符。

示例

cpp

// new - 简洁,不易错
MyClass* p1 = new MyClass;
MyClass* pArray = new MyClass[10]; // 分配 10 个对象的数组// malloc - 繁琐,易错
MyClass* p2 = (MyClass*)malloc(sizeof(MyClass)); // 必须用 sizeof
MyClass* pArray2 = (MyClass*)malloc(10 * sizeof(MyClass)); // 必须计算总大小
// 如果 MyClass 有自定义对齐要求,malloc 可能无法满足,而 new 可以。
5. 重载
  • new/delete:可以针对自定义类进行重载,实现自定义的内存管理策略(例如使用内存池)。

  • malloc/free不能被重载

示例

cpp

class MyClass {
public:void* operator new(size_t size) {std::cout << "Custom new for size: " << size << '\n';return ::operator new(size); // 调用全局的 new}void operator delete(void* ptr) {std::cout << "Custom delete\n";::operator delete(ptr); // 调用全局的 delete}
};int main() {MyClass* obj = new MyClass; // 输出: Custom new for size: 1delete obj;                 // 输出: Custom delete
}

结论与建议

场景推荐使用
C++ 中分配单个对象new
C++ 中分配对象数组new[]
C++ 中释放对象delete
C++ 中释放对象数组delete[]
C 语言编程malloc / free
分配原始内存(与 C 接口交互)malloc / free
实现自定义内存分配器重载 operator new / operator delete

绝对不要混用!用 new 分配的内存必须用 delete 释放;用 malloc 分配的内存必须用 free 释放;用 new[] 分配的内存必须用 delete[] 释放。混用会导致未定义行为,通常是程序崩溃。

在现代 C++ 中,为了更好的安全性和简洁性,应该优先使用智能指针(如 std::unique_ptr, std::shared_ptr),它们内部使用 newdelete,但能自动管理生命周期,从而完全避免显式地使用 newdelete

http://www.xdnf.cn/news/1389817.html

相关文章:

  • 小杰机器视觉(five day)——直方图均衡化
  • linux系统学习(13.系统管理)
  • 基于orin系列的刷写支持笔记
  • 30分钟入门实战速成Cursor IDE(1)
  • 【拍摄学习记录】04-拍摄模式/曝光组合
  • Nginx的主要配置文件nginx.conf详细解读——及其不间断重启nginx服务等操作
  • 数据结构—第五章 树与二叉树
  • 机器学习算法全景解析:从理论到实践
  • vue3 鼠标移上去 显示勾选框 选中之后保持高亮
  • 自然语言提取PDF表格数据
  • 马斯克杀入AI编程!xAI新模型Grok Code Fast 1发布,深度评测:速度、价格与API上手指南
  • Vue3 + Spring Boot 项目中跨域问题的排查与解决
  • CS144 lab3 tcp_sender
  • 自动驾驶中的传感器技术36——Lidar(11)
  • 《生成式AI消费级应用Top 100——第五版》| a16z
  • uni-app 跨平台项目的 iOS 上架流程:多工具组合的高效协作方案
  • driver.js实现前端页面引导
  • 【Flask】测试平台开发,集成禅道
  • 渗透测试学习笔记
  • dm8_静默安装简单快速
  • 基于EB的K3XX_GPT定时器中断的实现方法
  • 音视频直播卡顿分析与优化:技术原理、实践案例与未来趋势
  • Java 流(Stream)、文件(File)和IO
  • 基于 Python asyncio 和币安 WebSocket 打造高频加密货币预警机器人
  • 【Spring Cloud Alibaba】前置知识
  • 订餐后台项目-day02数据库模型定义笔记
  • 从0开始学习Java+AI知识点总结-28.Linux部署
  • Java 8核心特性详解:从Lambda到Stream的革命性升级
  • lesson49:HTML基础标签全解析:从入门到精通的网页构建指南
  • SQL Server 查看备份计划