unique_ptr 不能复制只能移动,出生即绑定资源、析构自动释放;最安全创建方式是 std::make_unique,支持数组和自定义删除器,访问前需判空,release/reset 控制释放,误用易致未定义行为。
unique_ptr 不能复制,只能移动;它一出生就绑定资源,析构时自动释放——这是它实现独占式资源管理的核心机制。
最安全的方式是用 std::make_unique,它避免裸 new 可能引发的异常安全问题(比如构造参数中抛异常导致内存泄漏)。
auto ptr = std::make_unique(42);
std::unique_ptr(裸 new 容易出错,且无法传递数组长度)ptr(new int(42));
auto arr = std::make_unique,此时调用的是(10); // 注意 [] 语法
delete[]
std::unique_ptrptr(new int(42), [](int* p) { delete p; });
拷贝语义会破坏“独占”前提:两个指针同时指向同一块内存,谁析构谁负责?unique_ptr 的拷贝构造函数和 operator= 都被显式 delete 了。
auto p1 = std::make_unique(1); auto p2 = p1; // 编译失败:use of deleted function
auto p2 = std::move(p1); // p1 变成 nullptr,p2 持有资源
void take(std::unique_ptrp) { /* p 接收所有权 */ } auto p = std::make_unique (1); take(std::move(p)); // p 此后为空
直接解引用前务必检查是否为空,否则触发未定义行为;显式释放用 release(),但要自己承担后续释放责任。
ptr.get() 返回原始指针(只读),*ptr 或 ptr->member 解引用(需确保非空)if (ptr) 或 if (ptr != nullptr),别用 if (ptr.get()) 多此一举int* raw = ptr.release(); // ptr 变成 nullptr,raw 必须手动 delete
ptr.reset(new int(99)) 会先释放旧资源再接管新资源;ptr.reset() 等价于 ptr = nullptr
最容易被忽略的是数组类型和自定义删除器的匹配问题——类型系统不会帮你校验删除器逻辑是否正确。
make_unique 创建数组,却用普通 unique_ptr 接收 → 编译报错(类型不匹配)unique_ptr 管理 → delete 而非 delete[],UBunique_ptr 存入容器(如 std::vector<:unique_ptr>>)没问题,但存进 std::set 或作为 std::map key 就不行——因为不可比较、不可拷贝unique_ptr(尤其带自定义删除器)可能因 ABI 不一致崩溃,优先用裸指针 + 明确约定生命周期真正难的不是语法,而是判断“该不该用 unique_ptr”:如果资源需要共享或延迟释放,它就不是解;如果对象生命周期本就由栈管理,加一层 unique_ptr 反而增加间接性。它的价值只在“我确定只有我管这块内存,且我走的时候必须清掉”。