new和delete是c++中管理堆内存的核心操作,自动调用构造/析构函数;需配对使用、区分数组与单对象,避免泄漏、重复释放等错误。

new 和 delete 是最直接的动态内存分配方式
在 C++ 中,new 和 delete 是管理堆内存的核心操作,它们会调用全局或类特定的内存分配/释放函数(如 operator new 和 operator delete),并自动调用构造/析构函数——这点和 C 的 malloc/free 有本质区别。
常见错误现象包括:用 delete 释放 malloc 分配的内存、用 delete[] 释放非数组对象、重复 delete 同一指针、或忘记 delete 导致内存泄漏。
-
int* p = new int(42);分配单个int并初始化为 42;必须用delete p;释放 -
int* arr = new int[10];分配 10 个未初始化的int;必须用delete[] arr;释放,否则行为未定义 - 如果类有自定义构造函数,
new MyClass{...}会调用它;而malloc(sizeof(MyClass))不会
为什么 vector 比裸 new 更安全可靠
手动用 new[] 分配数组后,要自己记录长度、管理生命周期、处理异常安全——稍有疏忽就容易出错。而 std::vector 把这些都封装好了,底层仍用 new,但对外屏蔽了细节。
使用场景:需要可变大小容器、频繁增删元素、或需保证异常安全时,优先选 vector。
- 初始化:
std::vector<int> v{1, 2, 3};</int>或v.reserve(100);预分配空间 - 扩容时,
vector会自动new更大内存块、拷贝/移动元素、delete旧块——你不用管 - 离开作用域自动析构,不会漏掉释放;抛异常时也能保证资源清理(RAII)
operator new 失败时默认抛出 std::bad_alloc
标准 operator new 在内存不足时抛出 std::bad_alloc 异常,而不是返回 nullptr。这点和 C 的习惯不同,容易导致未捕获异常而程序终止。
如果你需要类似 malloc 的失败返回行为,得显式使用“无抛出”版本:
-
int* p = new(std::nothrow) int[1000000];—— 分配失败时返回nullptr,不抛异常 - 之后必须检查:
if (!p) { /* 处理失败 */ } - 注意:即使用了
nothrow,构造函数仍可能抛异常(比如std::vector初始化失败),所以不能完全避免异常
自定义分配器适合高频小对象场景
频繁 new/delete 小对象(比如链表节点、树节点)会导致堆碎片和性能下降。这时可写一个池式分配器,预先申请大块内存,按固定大小切分复用。
但别过早优化:标准库分配器已针对通用场景做了大量优化;只有 profiler 确实指出分配是瓶颈时,才值得动手。
- 实现关键点:重载类的
operator new和operator delete,或给vector等容器传入自定义分配器类型 - 注意:自定义分配器必须满足 C++ 标准对分配器的要求(比如可复制、比较相等性),否则容器行为未定义
- 调试时可用
malloc_hook(glibc)或_malloc_dbg(MSVC)追踪分配来源,但仅限开发环境
真正难的不是写出 new,而是判断该不该用、在哪用、以及谁来负责释放——尤其在跨模块、多线程或异常路径中,裸指针的生命周期边界很容易模糊。现代 C++ 更推荐用 std::unique_ptr、std::shared_ptr 显式表达所有权,把“谁释放”的问题交给类型系统管。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











