shared_ptr默认不支持数组,直接使用会因调用delete而非delete[]导致未定义行为;必须通过自定义删除器(如lambda或std::default_delete<int[]>)显式指定delete[],或优先选用std::vector替代。

shared_ptr 默认不支持数组,直接用会崩溃
直接写 std::shared_ptr<int> ptr(new int[10])</int> 看似能编译,但析构时调用的是 delete 而不是 delete[],导致未定义行为——常见表现是程序在析构时 crash 或内存泄漏。C++11 标准明确要求:裸指针指向数组时,必须配对使用 delete[],而 shared_ptr 默认删除器只认 delete。
用自定义删除器(deleter)正确释放数组
给 shared_ptr 指定一个执行 delete[] 的删除器,是最常用且安全的做法:
std::shared_ptr<int> ptr(new int[5], [](int* p) { delete[] p; });关键点:
- 删除器必须是可调用对象(lambda、函数指针或 functor),类型需匹配
std::shared_ptr<T>中的T(这里是int*) - 不能写成
std::shared_ptr<int[]>—— 这种写法虽能编译,但operator[]行为未定义,且无法通过类型系统保证删除器正确 - 如果数组元素类型是非平凡析构类型(如
std::string),delete[]仍会正确调用每个元素的析构函数
更安全的选择:用 std::vector 替代裸数组
除非对接 C API 或有严格内存布局要求,否则优先用 std::vector:
立即学习“C++免费学习笔记(深入)”;
auto vec = std::make_shared<std::vector<int>>(10); // 10 个默认初始化的 int
优势明显:
- 自动管理大小和容量,支持
push_back、resize等操作 - 无需手动指定删除器,析构安全无歧义
- 与算法、范围 for 循环天然兼容
- 若需共享底层存储但不同 size 视图,可用
std::span(C++20)配合shared_ptr<vector>
shared_ptr<T[]> 在 C++17 后的有限支持
C++17 引入了对数组类型的模板特化,允许写 std::shared_ptr<int[]>,但它只解决类型声明问题,不自动绑定 delete[]:
std::shared_ptr<int[]> ptr(new int[5]); // ❌ 仍调用 delete,UB
必须显式提供删除器才能安全使用:
std::shared_ptr<int[]> ptr(new int[5], std::default_delete<int[]>{}); // ✅ OK注意:
-
std::default_delete<int[]>是标准库提供的专用删除器,等价于[](int* p) { delete[] p; } -
shared_ptr<int[]>不支持get()后直接用[]访问(因类型是int[],非int*),实际仍要靠get()取出原始指针再索引 - 这种写法易误导,且可读性差,不推荐日常使用
真正麻烦的不是怎么写删除器,而是忘记它——只要用了 new[],就必须显式配对 delete[],哪怕包装在 shared_ptr 里也不会自动推断。


















