delete与delete[]混用会导致未定义行为:unique_ptr数组版需声明为T[]并自动调用delete[],shared_ptr则必须显式传入delete[]删除器,否则默认用delete释放数组将崩溃。

delete 和 delete[] 混用导致的删除器不匹配
智能指针默认用 delete 释放内存,但数组必须用 delete[]。如果用 std::unique_ptr<t></t> 却没显式指定删除器,或误用了非数组版本,运行时可能崩溃或触发未定义行为——尤其在析构时调用错误的释放函数。
-
std::unique_ptr<int></int>管理单个int:用delete正确 -
std::unique_ptr<int></int>管理new int[10]:必须用delete[],且类型声明必须带[] - 若写成
std::unique_ptr<int> p(new int[10])</int>,即使手动传[](int* p){ delete[] p; },类型不匹配仍会编译失败(无法隐式转换)
std::unique_ptr 的正确写法和常见误写
数组版 std::unique_ptr 是特化类型,不是模板参数加个 [] 就行——它自带适配的删除器,不需要手写 lambda,但类型声明必须严格匹配。
- ✅ 正确:
std::unique_ptr<int> p(new int[5]);</int>—— 自动调用delete[] - ❌ 错误:
std::unique_ptr<int> p(new int[5]);</int>—— 类型不兼容,编译报错 - ❌ 错误:
std::unique_ptr<int> p(new int(5));</int>—— 用new int(5)分配单个对象,却用数组版智能指针,析构时调delete[]导致 UB - ⚠️ 注意:
p.get()返回的是int*,不是int[]*;下标访问p[i]合法,但p + i或取地址需谨慎
std::shared_ptr 管理数组需要自定义删除器
std::shared_ptr 没有内置数组特化,必须显式传入 delete[] 删除器,否则默认用 delete,必然出错。
- ✅ 正确:
std::shared_ptr<int> p(new int[10], [](int* ptr){ delete[] ptr; });</int> - ✅ 更安全(避免裸 new):
auto raw = new int[10]; std::shared_ptr<int> p(raw, [](int* ptr){ delete[] ptr; });</int> - ⚠️ 风险点:lambda 捕获不能用
[&]或[=],必须是空捕获[],否则无法转换为函数指针(shared_ptr构造要求可拷贝/可转移的删除器) - ⚠️ 不要写成
std::shared_ptr<int> p(...)</int>—— 这仍是shared_ptr的普通实例化,[]在模板参数里无意义,不会触发特殊行为
用 std::vector 替代裸数组更简单可靠
除非有明确的 ABI 兼容、C 接口互操作或性能敏感场景,否则优先用 std::vector。它自动管理堆内存、支持移动、提供迭代器和容量控制,彻底绕过删除器匹配问题。
立即学习“C++免费学习笔记(深入)”;
- 替代
std::unique_ptr<int></int>:std::vector<int> v(10);</int>—— 无需关心 new/delete - 替代
std::shared_ptr<int></int>+ 自定义删除器:std::shared_ptr<:vector>> pv = std::make_shared<:vector>>(10);</:vector></:vector> - 唯一例外:需要返回 C 风格数组给外部 API 时,可用
v.data()获取指针,但生命周期仍由vector控制
数组智能指针的坑不在语法多难,而在类型系统对 new/new[] 的零容忍——差一个方括号,就是未定义行为的开始。


















