该用 unique_ptr 而不是裸指针时:需动态分配对象且明确不共享所有权,它自动管理生命周期、禁止拷贝、零运行时开销,适用于局部对象、容器存储、工厂返回等场景。

什么时候该用 unique_ptr 而不是裸指针
当你需要动态分配对象、又明确不希望它被多个所有者共享时,unique_ptr 是裸指针最直接的替代品。它自动管理生命周期,避免忘记 delete 导致的内存泄漏;同时禁止拷贝,从编译期就堵死“意外共享”的漏洞。
典型场景包括:函数内局部动态对象、容器中存放独占资源、工厂函数返回堆对象。
- 如果对象生命周期和作用域完全一致(比如只在当前函数里用),
unique_ptr比shared_ptr更轻量,无引用计数开销 - 若需把堆对象传给另一个函数并移交所有权,用
std::move()转移,而不是传引用或指针 - 不能用
unique_ptr存储 C 风格数组(如new int[10])而不指定自定义删除器——否则会调用delete而非delete[],导致未定义行为
unique_ptr 的三种常见构造方式
构造方式直接影响资源管理行为,尤其注意默认删除器和数组特化版本的区别。
- 默认构造:
std::unique_ptr<int> p;</int>→ 空指针,不持有资源 - 带原始指针构造:
std::unique_ptr<int> p(new int(42));</int>→ 使用默认删除器delete,适用于单个对象 - 带数组类型和
delete[]删除器:std::unique_ptr<int> p(new int[5]);</int>→ 类型必须是T[],自动调用delete[]
错误示范:std::unique_ptr<int> p(new int[5]);</int> 编译通过但运行时析构出错——因为类型不匹配,删除器仍用 delete。
转移所有权时为什么必须用 std::move()
unique_ptr 禁止拷贝,只允许移动。直接赋值或传参会触发编译错误,提示 “use of deleted function”。
- 函数返回:
auto create() { return std::unique_ptr<int>(new int(1)); }</int>—— 返回值自动移动,无需显式std::move - 函数参数传递:
void take(std::unique_ptr<int> p) { ... }</int>,调用时必须写take(std::move(p)),否则报错 - 容器插入:
std::vector<:unique_ptr>> v; v.push_back(std::move(p));</:unique_ptr>,否则push_back尝试拷贝失败
漏掉 std::move 是新手最高频的编译错误之一,错误信息里通常含 “copy constructor is deleted” 或 “no matching function for call to …”。
如何安全访问 unique_ptr 所指对象
解引用和成员访问语法与裸指针一致,但要注意空指针检查——unique_ptr 不保证非空。
- 解引用:
*p,等价于*p.get();若p为空,行为未定义 - 成员访问:
p->func(),同样要求p非空 - 获取原始指针:
p.get(),仅用于传递给 C 接口或 legacy 函数,**不移交所有权** - 释放控制权:
p.release()→ 返回原始指针,p变为空,后续需手动delete
最容易忽略的是:get() 返回的指针不带生命周期保障,绝不能存为裸指针长期使用;而 release() 后忘记 delete 就等于退回到手动内存管理的老问题。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











