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

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

C++ 中 new/deletemalloc/free 完全详解


一、new/deletemalloc/free 的区别

特性new/deletemalloc/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 示例

#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 示例

#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[](数组版本)

#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;
}

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

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

五、常见错误示例

// 错误示例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/freenew/delete
只分配/释放内存,不调用构造析构函数分配内存并调用构造/析构函数
返回 void*返回对应类型的指针
C 风格C++ 风格
适合简单内存申请(不需要对象管理)适合对象创建与销毁(有构造析构过程)
http://www.xdnf.cn/news/3023.html

相关文章:

  • gradle 下载的tencent的镜像
  • 为什么 Vite 速度比 Webpack 快?
  • STM32单片机入门学习——第49节: [15-2] 读写内部FLASH读取芯片ID
  • 【行业特化篇3】制造业简历优化指南:技术参数与标准化流程的关键词植入艺术
  • 在Spark中通过jps命令看到的进程名,是哪个命令产生有什么作用
  • 亚远景-ASPICE认证:如何优化软件开发流程?
  • js 正则中的$0,1,2,3 是怎么用的
  • 解析表观遗传学的工具——ChIP-seq(二)
  • 博客打卡-小易喜欢的数列-动态规划
  • python数据分析(六):Pandas 多数据操作全面指南
  • JAVA 枚举类的ordinal用法
  • JavaScript中 说说你对闭包的理解?闭包使用场景?
  • Java练习8
  • GBDT算法原理及Python实现
  • 2024jxcpc D.Magic LCM (logn筛质因子)
  • 百度CarLife实现手机车机无缝互联
  • BT134-ASEMI机器人功率器件专用BT134
  • 告别碎片化!两大先进分块技术如何提升RAG的语义连贯性?
  • 【系统参数合法性校验】spring-boot-starter-validation
  • PowerBI更新后出现提示,无法正常使用,解决办法
  • JavaScript == 和 ===区别,分别在什么情况使用?
  • 角度(degrees)和弧度(radians)转换关系
  • Oracle OCP证书有效期是三年?
  • 5 个开源 MCP 服务器
  • 【MongoDB篇】MongoDB的集合操作!
  • 【angular19】入门基础教程(四):默认的css隔离作用域
  • 基于Java,SpringBoot,HTML水文水质监测预警系统设计
  • 【最新 MCP 战神手册 08】工具使用详解:实现 AI 行动
  • 动态图表 -- eg1
  • Femap许可分配和监控