std::unique_ptr 是 C++11 引入的智能指针,用于管理动态分配的内存,通过独占所有权和自动释放机制提升代码安全性。以下是其核心要点及使用示例:
1. 核心特性
- 独占所有权:同一时间只能有一个
unique_ptr拥有资源,禁止复制,支持移动语义(通过std::move)。 - 自动释放:当
unique_ptr离开作用域或被重置时,自动释放其管理的资源。 - 轻量高效:默认无额外内存开销,性能与裸指针相当。
2. 基础用法
创建与初始化
- 单个对象:
std::unique_ptr<int> ptr1 = std::make_unique<int>(42); // 推荐:安全且高效 std::unique_ptr<Widget> ptr2(new Widget()); // 直接构造(需谨慎) - 数组(C++14 起支持
T[]):std::unique_ptr<int[]> arr = std::make_unique<int[]>(10); // 管理动态数组
所有权转移
auto ptr1 = std::make_unique<int>(100);
auto ptr2 = std::move(ptr1); // ptr1 变为 nullptr,ptr2 获得所有权
主动释放资源
ptr2.reset(); // 释放资源并将 ptr2 置空
int* raw_ptr = ptr2.release(); // 返回原始指针,ptr2 置空(需手动管理 raw_ptr)
3. 高级用法
自定义删除器
- 函数指针形式:
auto deleter = [](FILE* f) { fclose(f); }; std::unique_ptr<FILE, decltype(deleter)> file_ptr(fopen("data.txt", "r"), deleter); - 状态化删除器(需额外存储空间):
struct CustomDeleter { void operator()(int* p) { delete p; /* 其他操作 */ } }; std::unique_ptr<int, CustomDeleter> ptr(new int, CustomDeleter());
作为函数参数
- 传递所有权:
void take_ownership(std::unique_ptr<Widget> ptr) { /* ... */ } auto widget = std::make_unique<Widget>(); take_ownership(std::move(widget)); // 所有权转移至函数内部 - 仅访问资源(避免所有权转移):
void use_resource(const Widget& obj) { /* ... */ } auto widget = std::make_unique<Widget>(); use_resource(*widget); // 传递引用,保留所有权
4. 注意事项
- 禁止复制:
std::unique_ptr<int> ptr1 = std::make_unique<int>(10); // std::unique_ptr<int> ptr2 = ptr1; // 错误:尝试复制 - 避免悬空指针:
int* raw = ptr1.get(); // 获取原始指针(不释放所有权) // 确保 raw 在 ptr1 有效期内使用 - 异常安全:
void safe_function() { auto ptr = std::make_unique<Resource>(); // 即使后续代码抛出异常,ptr 仍会释放资源 // 可能抛出异常的操作 }
5. 性能与适用场景
- 零额外开销:默认删除器通过空基类优化,大小等于裸指针。
- 适用场景:
- 管理动态对象或数组。
- 作为工厂函数返回值(明确所有权转移)。
- 替代
new/delete手动内存管理。
示例:管理动态数组
#include <memory>
#include <iostream>
int main() {
// 创建管理 int 数组的 unique_ptr
std::unique_ptr<int[]> arr = std::make_unique<int[]>(5);
for (int i = 0; i < 5; ++i) {
arr[i] = i * 2;
}
// 输出数组内容
for (int i = 0; i < 5; ++i) {
std::cout << arr[i] << " "; // 输出:0 2 4 6 8
}
// 自动释放数组内存(无需手动 delete[])
return 0;
}
总结
std::unique_ptr 是 C++ 中管理动态内存的首选工具,通过强制独占所有权和自动释放机制,显著减少内存泄漏和资源管理错误。优先使用 std::make_unique 创建实例,仅在需要时使用自定义删除器或裸指针操作。
2112

被折叠的 条评论
为什么被折叠?



