unique_ptr不可拷贝只能移动,需用std::move转移所有权;推荐std::make_unique创建,异常安全;数组须用特化版本;函数传参优先按值移动或裸指针/引用。

unique_ptr 不能被拷贝,只能移动
这是最常踩的坑:直接写 std::unique_ptr 会编译失败,报错类似 use of deleted function。因为 unique_ptr 的拷贝构造函数和拷贝赋值运算符都被显式删除了,它只允许转移所有权。
正确做法是用 std::move 显式转移:
std::unique_ptrp1 = std::make_unique (42); std::unique_ptr p2 = std::move(p1); // p1 现在为空,p2 持有资源
注意:p1 被移动后变成空指针(p1 == nullptr),再解引用会崩溃。
make_unique 是首选创建方式,别手动 new
用 new 配合 unique_ptr 构造函数容易出异常安全问题。比如 std::unique_ptr 中,若 Foo 构造抛异常,new 分配的内存就泄露了。
立即学习“C++免费学习笔记(深入)”;
std::make_unique 是异常安全的,且更简洁:
-
std::make_unique→ 初始化为 0() -
std::make_unique→ 初始化为 123(123) -
std::make_unique<:string>("hello")→ 正确转发参数
例外:需要自定义删除器时,仍需显式构造,例如 std::unique_ptr。
数组版本 unique_ptr 必须显式声明
很多人误以为 std::unique_ptr 能自动管理数组——不行。这会导致只调用 delete 而非 delete[],UB(未定义行为)。
必须用数组特化版本:
auto arr = std::make_unique(10); // OK,自动用 delete[] arr[0] = 1; // 不要这样:std::unique_ptr p(new int[10]); // 危险!
数组版不支持 operator* 和 operator->,只支持 [] 和 get()。
作为函数参数传递时,按值 or 按引用?
传入函数表示“交出所有权”,用按值传递 + std::move:
void consume(std::unique_ptrptr) { /* ptr 独占资源 */ } consume(std::move(p)); // p 失去所有权
如果只是临时观察或修改所指对象,不要传 unique_ptr,传 int& 或 int* 更清晰、零开销:
void inspect(const int& x) { /* 只读 */ }
inspect(*p); // 安全,p 非空前提下传 const std::unique_ptr 是反模式:既没获得所有权,又绑定了一个本不该长期持有的智能指针引用。
真正麻烦的是跨线程传递和自定义删除器的生命周期管理——这两处稍不注意,就会让 unique_ptr 在错误时机释放资源,尤其是删除器捕获了局部变量或依赖外部状态时。











