必须用 std::move 转移 std::unique_ptr 所有权,因拷贝被禁用;转移后原指针变空,访问将导致未定义行为;函数返回时无需显式 std::move,容器插入等场景则必须使用。

直接用 std::move 转移所有权,别试赋值或拷贝
不能用 = 直接赋值,也不能写 ptr2 = ptr1(编译失败),因为 std::unique_ptr 禁用了拷贝构造和拷贝赋值。唯一合法方式是显式转移——用 std::move。
-
std::unique_ptr的设计原则就是“独占所有权”,转移后原指针自动变为空(nullptr) - 必须用
std::move(ptr1),写成ptr2 = ptr1会触发删除器调用并崩溃(如果ptr1非空) - 转移前后类型必须匹配:指向同一类型,且删除器兼容(默认删除器可隐式转换,自定义删除器需显式匹配)
转移后原 unique_ptr 变成空,访问会段错误
转移不是“复制”,而是“移交控制权”。一旦执行 ptr2 = std::move(ptr1),ptr1.get() 返回 nullptr,再解引用或调用 -> 就是未定义行为。
- 常见错误:转移后还对
ptr1调用reset()或release()—— 安全但无意义;调用*ptr1或ptr1->foo()会 crash - 调试时可用
if (ptr1) { ... }判断是否仍持有对象,转移后这个条件为 false - 若需保留原指针的“空状态”语义,无需手动
ptr1.reset(),std::move已保证它为空
函数返回或参数传递时,std::move 不是必须写的场景
在函数返回局部 unique_ptr 时,编译器通常自动应用移动语义(RVO + 移动优化),显式写 std::move 反而可能阻止优化。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 返回时:
return local_ptr;✅ 推荐;return std::move(local_ptr);❌ 不必要,且可能抑制返回值优化 - 函数参数是右值引用(如
void take(std::unique_ptr<int>&& p)</int>),调用时需take(std::move(ptr)) - 容器插入(如
vec.push_back(std::move(ptr)))必须写std::move,否则编译失败
跨类型转移需注意指针类型和删除器兼容性
把 std::unique_ptr<derived></derived> 转给 std::unique_ptr<base> 是允许的(多态转移),但反过来不行;删除器不匹配会导致编译错误。
立即学习“C++免费学习笔记(深入)”;
- 上行转换(派生→基类)自动安全:
std::unique_ptr<child> c = std::make_unique<child>(); std::unique_ptr<parent> p = std::move(c);</parent></child></child> - 下行转换(基类→派生)需
static_cast或自定义转换,且不推荐——容易破坏类型安全 - 自定义删除器(如
std::unique_ptr<int mydeleter></int>)转给默认删除器会失败,除非删除器类型可隐式转换
unique_ptr,只是不再指向任何对象。

















