std::unique_ptr是管理动态数组的首选,因默认delete会引发未定义行为;必须显式指定数组类型并用delete[]析构,shared_ptr需自定义删除器,vector更安全常用。

std::unique_ptr 是管理动态数组的首选
直接用 std::unique_ptr<int></int> 去接 new int[10] 会崩溃——析构时调用的是 delete 而非 delete[],导致未定义行为。必须显式指定数组类型:用 std::unique_ptr<int></int>,它内置了对 delete[] 的正确调用。
常见错误现象:double free or corruption、程序在析构时 SIGABRT、Valgrind 报 Mismatched free() / delete / delete []。
-
std::unique_ptr<int></int>构造时只能传裸指针(如new int[5]),不能传普通数组或栈变量 - 访问元素用
ptr[i],不是ptr->at(i)(operator[]已重载) - 不支持
get()返回的指针做算术运算后直接 delete —— 必须保证原始指针地址被传入构造函数 - 不能用
reset(new int[3])多次分配,否则前一次内存泄漏;应改用reset()清空后再 new
std::shared_ptr 需要自定义删除器才能安全使用
std::shared_ptr 默认删除器是 delete,对数组无效。若强行用 std::shared_ptr<int></int>,编译可能通过(C++17 起允许),但实际仍调用 delete,风险同上。
正确做法是显式绑定 delete[] 删除器:
auto ptr = std::shared_ptr<int>(new int[5], [](int* p) { delete[] p; });</int>
注意:lambda 删除器必须捕获为空([]),不能按引用捕获外部变量,否则可能延长生命周期引发悬挂。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 删除器类型需与指针类型匹配:
int*对应void(*)(int*),不能传std::default_delete<int></int>(它不是可调用对象) - 不能用
std::make_shared<int>(n)</int>—— 标准库不支持数组版make_shared(C++20 仍未加入) - 共享计数开销存在,若只是内部临时数组,优先选
unique_ptr
vector 比智能指针管理数组更常用也更安全
90% 的动态数组场景,std::vector 是更自然的选择:自动管理内存、支持移动语义、提供 data() 获取原始指针、能直接和 C API 交互。
例如需要传给 C 函数的连续内存:
std::vector<int> v(10); some_c_function(v.data(), v.size());</int>
-
vector在 resize 或 push_back 时可能重新分配,data()指针失效;需确保生命周期内不触发扩容 - 若需固定大小且不增删,
std::array(栈上)或std::vector(堆上)比裸 new + 智能指针更易维护 - 跨 DLL 边界传递
vector有 ABI 风险;此时才考虑用unique_ptr<t></t>+ 明确内存所有权约定
不要混用智能指针和 raw pointer 管理同一块数组
一个 int* 被 unique_ptr 接管后,再用 delete[] 手动释放,必然 double-free。反过来,如果先 delete[] 了,智能指针析构时再删一次,同样崩溃。
- 裸指针一旦交给智能指针,就彻底放弃手动管理权
- 函数参数中接收
int*并不意味着你能 delete 它;必须明确文档或接口契约:谁负责释放 - 调试时可用 AddressSanitizer 检测 use-after-free 和 double-free,比靠经验更可靠
智能指针管数组的关键不是语法多难,而是删错操作符的后果太隐蔽——崩溃常发生在程序退出析构阶段,而不是 new 的地方。务必确认模板参数带 []、删除器写对、且全程不掺杂裸指针干预。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










