std::unique_ptr必须使用<int[]>特化版本管理动态数组,否则析构时调用delete而非delete[],导致未定义行为;它支持operator[]但禁用operator*和operator->,推荐用std::make_unique<int[]>(N)构造。

std::unique_ptr 必须带方括号才能正确析构数组
直接用 std::unique_ptr<int></int> 指向 new int[10] 是危险的——它会调用 delete 而非 delete[],导致未定义行为,常见表现是内存泄漏或崩溃。
正确做法是显式使用数组特化版本:std::unique_ptr<int></int>。这个类型重载了 [] 运算符,且析构时自动调用 delete[]。
-
std::unique_ptr<int> ptr(new int[5]);</int>✅ 安全 -
ptr[2] = 42;—— 支持下标访问 - 不能用
ptr.get()返回的裸指针去delete[],智能指针仍拥有所有权 - 不支持
ptr.release()后再手动delete[],除非你明确接管并确保只释放一次
std::shared_ptr 需要自定义删除器才能安全管理数组
std::shared_ptr 默认没有 T[] 特化(C++17 前),即使写成 std::shared_ptr<int></int>,底层仍可能调用 delete 而非 delete[],除非显式提供删除器。
最稳妥写法是绑定 std::default_delete<int></int>:
立即学习“C++免费学习笔记(深入)”;
std::shared_ptr<int> ptr(new int[10], std::default_delete<int[]>());
注意:这里模板参数仍是 int(不是 int[]),删除器才是关键。也可以写成:
std::shared_ptr<int[]> ptr(new int[10], [](int* p) { delete[] p; });- 自定义 lambda 删除器更直观,但要注意捕获为空(
[]),避免意外引用 - 不要传入
std::default_delete<int></int>—— 它会错用delete - 共享数组时,拷贝
shared_ptr是安全的;但无法像unique_ptr<t></t>那样直接用ptr[i],需先解引用:(*ptr)[i]或ptr.get()[i]
不要用 std::make_unique 或 std::make_shared 创建动态数组
std::make_unique<int>(10)</int> 在 C++14 及之后是合法的,会构造长度为 10 的数组并值初始化,推荐优先使用:
auto ptr = std::make_unique<int[]>(10); // ✅ 安全、简洁、异常安全
但 std::make_shared<int>(n)</int> **不被标准支持**,所有主流编译器(GCC、Clang、MSVC)都拒绝该用法。试图绕过会触发编译错误,例如:
error: no matching function for call to 'make_shared<int>'</int>
-
make_unique支持数组,make_shared不支持 —— 这不是疏漏,而是因shared_ptr内部控制块与对象需连续分配,而数组大小在运行时才确定,难以统一布局 - 若必须用
shared_ptr管理数组,请坚持用带删除器的原始构造方式 -
make_unique创建的数组无法指定自定义初始化值(如全 1),只能值初始化(int()→ 0);需要定制初始化得手写new+ 删除器
raw pointer 转智能指针时,删除器匹配比类型名更重要
从 C API 或遗留代码拿到 int* 数组时,别只看变量声明,重点确认它是否由 new[] 分配。哪怕类型是 int*,只要源头是 new[],就必须配 delete[]。
- 错误示范:
std::shared_ptr<int>(raw_ptr)</int>—— 默认删器是delete,必崩 - 正确写法:
std::shared_ptr<int>(raw_ptr, [](int* p) { delete[] p; })</int> - 如果数组来自
malloc,就得用free删除器:std::shared_ptr<int>(raw_ptr, free)</int> -
unique_ptr同理:用std::unique_ptr<int void></int>显式指定删除器类型,再传入函数指针或 lambda
数组生命周期管理的复杂点不在语法,而在“谁分配、怎么分配、谁负责释放”的契约一致性。类型系统不会替你记住 new[] 和 new 的区别,删器写错,程序可能跑很久才出问题。


















