unique_ptr的move语义是唯一合法的所有权转移方式,直接赋值或拷贝会编译失败;转移后原指针置为nullptr,需用std::move()显式触发,函数传参用值传递,容器插入需push_back(std::move(p)),reset()安全放弃所有权,release()移交裸指针需手动delete,误用易致泄漏或崩溃。

unique_ptr 的 move 语义是唯一合法的所有权转移方式
直接赋值或拷贝 unique_ptr 会编译失败,这不是限制,而是设计核心:它强制你显式表达“我把控制权交出去了”。所有权转移只能通过 std::move() 触发移动构造或移动赋值,此时原指针自动置为 nullptr,避免悬空和重复释放。
常见错误现象:error: use of deleted function 'std::unique_ptr —— 这说明你写了 p2 = p1 或 func(p1) 而没用 std::move。
- 函数传参时,想转移所有权就声明参数为
std::unique_ptr(值传递),调用时写func(std::move(p)) - 返回局部
unique_ptr不需要std::move(RVO/NRVO 和移动返回优化已覆盖) - 容器中存储
unique_ptr时,push_back(std::move(p))才能真正移入,否则编译不过
reset() 和 release() 的区别:一个清空,一个交出裸指针
reset() 是安全的“放弃所有权”操作:它先删除当前管理的对象(如果非空),再将内部指针设为 nullptr。而 release() 是“移交裸指针”,它只解绑不删除,把原始 T* 交给你,之后 unique_ptr 变成空,但你必须自己负责后续 delete —— 这是少数可能引入泄漏的点。
- 用
reset()替代手动delete+ 赋nullptr,更简洁且异常安全 -
release()仅在对接 C API 或特殊资源管理逻辑时需要,用完务必检查是否已delete - 误用
release()后忘记delete,会导致内存泄漏;误用reset()在不该删的时候删了,会导致提前释放
与 raw pointer 混用时最容易漏掉的空指针检查
unique_ptr 转移后变为空,但它的 get() 返回 nullptr,解引用会崩溃;而很多人习惯性地像用普通指针一样直接 *p 或 p->foo(),忘了它可能已被 move 走。
立即学习“C++免费学习笔记(深入)”;
- 转移后立即检查:
if (p) { ... }或用if (auto ptr = std::move(p)) { ... } - 调试时加断点看
p.get()值,比猜“应该还在”靠谱得多 - 禁止把
get()结果存为长期 raw pointer,除非你 100% 确保生命周期严格短于unique_ptr本身
std::move() 都意味着你主动切断了一个自动管理链,后面那根线得你自己攥紧。










