std::unique_ptr管理数组必须使用数组特化版本或std::make_unique(n),否则析构时调用delete而非delete[]导致未定义行为;支持operator[]访问元素,禁止operator*和operator->;仅支持移动,禁止拷贝。

std::unique_ptr 的声明方式必须带方括号
直接用 std::unique_ptr<int></int> 管理 new int[10] 会触发未定义行为——析构时调用的是 delete 而非 delete[],导致部分对象不被正确析构,甚至崩溃。必须显式使用数组特化版本:std::unique_ptr<int></int>。
常见错误现象:程序运行无报错但内存泄漏、对象析构函数没被调用、释放后访问(use-after-free)引发段错误。
-
std::unique_ptr<int> ptr(new int[5]);</int>✅ 正确 -
std::unique_ptr<int> ptr(new int[5]);</int>❌ 危险,delete误删数组 -
std::make_unique<int>(5)</int>✅ 推荐,更安全且自动零初始化
std::make_unique 是首选构造方式
std::make_unique 不仅避免裸 new,还天然适配数组类型,且默认对内置类型做值初始化(即零初始化),比手动 new 更可靠。
注意:不能用 std::make_unique<int>(5)</int> 初始化自定义类型数组并传参——它只支持默认构造;若需带参构造,仍需手动 new + 显式类型,但务必配对 std::unique_ptr<t></t>。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
auto arr = std::make_unique<int>(10);</int>→ 全部初始化为 0 -
auto arr = std::make_unique<:string>(3);</:string>→ 每个元素调用默认构造 -
std::unique_ptr<myclass> ptr(new MyClass[2]{MyClass(1), MyClass(2)});</myclass>→ 手动构造,类型必须匹配
访问数组元素只能用 operator[],不能用 operator*
std::unique_ptr<t></t> 重载了 operator[],但没有 operator* 或 operator->(因为数组首地址不是单个对象)。试图解引用会编译失败。
常见错误现象:*ptr 编译报错:error: invalid use of 'operator*' on unique_ptr to array type;ptr->foo() 同样不合法。
-
ptr[0] = 42;✅ 正确访问 -
ptr.get()[3] = 99;✅ 底层指针也可用,但没必要 -
ptr[5]→ 越界,不检查,行为未定义
移动语义可用,但拷贝被禁用
std::unique_ptr<t></t> 和普通 std::unique_ptr<t></t> 一样,只支持移动,禁止拷贝。这是所有权独占的体现,也避免了浅拷贝导致 double-delete。
性能影响:移动是 O(1) 操作,仅转移内部裸指针和 deleter(如有),无内存复制开销。但要注意:移动后原智能指针变为空(ptr == nullptr)。
-
auto a = std::make_unique<int>(100); auto b = std::move(a);</int>✅ 安全转移 -
auto b = a;❌ 编译错误:use of deleted function - 若自定义 deleter(如用
malloc/free),移动后 deleter 也会一并转移
[] 或误用 make_unique 参数形式,问题往往延迟到运行时才暴露。最稳妥的做法始终是:数组就用 std::unique_ptr<t></t> + std::make_unique<t>(n)</t>,别绕路。

















