[2.3-2]unique_ptr独占的智能指针

unique_ptr独占的智能指针

涉及的代码可在repo中找到:https://github.com/leoda1/the-notes-of-cuda-programming/tree/main/code/CPU

2.1 定义

unique_ptr是一个独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将 一个unique_ptr赋值给另一个unique_ptr

unique_ptr<T> p1(new T);
unique_ptr<T> p2 = p1; // 报错,不能复制

但可以通过std::move来转移到其他的unique_ptr,这样它本身就不再拥有原来指针的所有权了。例如:

unique_ptr<T> p1(new T);
unique_ptr<T> p2 = std::move(p1); // 正确

在c++14当中加入了std::make_unique,c++11中加入的是std::make_shared。 使用new的版本重复了被创建对象的键入,但是make_unique函数则没有。

auto upw1(std::make_unique<Widget>()); // with make func
std::unique_ptr<Widget> upw2(new Widget); // without make func

2.2 与shared_ptr的区别

  1. C++17中的shared_ptr才支持数组

  2. unique_ptr需要确定删除器的类型,所以不能像shared_ptr那样直接指定删除器,得这样写:

    std::shared_ptr<int> ptr3(new int(1), [](int *p){delete p;}); // 正确
    std::unique_ptr<int> ptr4(new int(1), [](int *p){delete p;}); // 错误
    std::unique_ptr<int, void(*)(int*)> ptr5(new int(1), [](int *p){delete p;}); //正确
    

    使用的时候会发现,这里的捕获列表加了&或者=就会报错。lambda 表达式的捕获列表(capture list)用于指定 lambda 表达式如何访问外部变量。当你为 lambda 表达式添加捕获列表(如 &=)时,lambda 表达式的类型会发生变化:从函数指针(如 void(*)(int*))
    变成了仿函数(闭包类型(closure type))。综上:使用unique_ptr的时候指定的是void()(int)类型,现在的lamba表达式是闭包类型,所以报错。

    需要将 std::unique_ptr 的删除器类型改为 std::function<void(int*)>,因为 std::function 可以存储任意可调用对象(包括有捕获的 lambda 表达式)。

    std::unique_ptr<int, std::function<void(int*)>> ptr5(new int(1), [&](int *p) {delete p;});
    
  3. 应用需求不同:如果希望只有一个智能指针管理资源或者管理数组就用unique_ptr,如果希望多个智能指针管理同一个资源就用shared_ptr。

<think>好的,用户想了解C++unique_ptr独占指针的应用场景和示例。我需要先回忆一下unique_ptr的基本特性,比如它的独占所有权、不可复制但可移动等特性。然后根据这些特性来思考适用的场景。 首先,根据引用[1]和[4],unique_ptr不能拷贝,只能移动,这保证了资源的独占管理。所以应用场景应该围绕所有权转移和资源安全释放展开。比如,在函数之间传递资源所有权时,使用unique_ptr可以避免内存泄漏。 引用[3]中提到,可以在容器中保存unique_ptr,这样容器内的元素可以管理动态分配的对象,而不用担心内存泄漏。这也是一个常见的应用场景。 另外,引用[3]还提到了使用unique_ptr管理动态数组,因为它支持数组的版本,比如unique_ptr<int[]>,这样可以自动释放数组内存,比原始指针更安全。 用户可能需要具体的例子,比如工厂模式返回对象,资源管理类中使用unique_ptr,或者在多态场景中管理派生类对象。比如工厂方法返回一个unique_ptr,确保调用方获得所有权,而不会有多个指针指向同一对象。 还要考虑异常安全的问题,unique_ptr在发生异常时能自动释放资源,避免泄漏。这也是一个重要的应用点。 需要检查每个引用中的示例,确保提供的例子正确,并符合用户的需求。比如引用[1]中的函数返回unique_ptr,引用[3]中的所有权转移和动态数组管理,引用[4]中的移动构造。 最后,组织这些场景,分点说明,每个场景给出代码示例,并引用对应的参考文献。确保回答结构清晰,示例准确,覆盖主要应用场景。</think>### C++ unique_ptr 独占指针使用场景与示例 `unique_ptr` 是 C++11 引入的智能指针,通过**独占所有权**机制确保资源的安全管理。以下是其核心应用场景及示例: --- #### 1. 函数返回动态分配对象的所有权 当函数需要返回动态分配的对象时,使用 `unique_ptr` 可明确所有权转移,避免内存泄漏。 ```cpp #include <memory> std::unique_ptr<int> create_int(int value) { return std::make_unique<int>(value); // 返回临时unique_ptr,触发移动语义 } int main() { auto ptr = create_int(42); // ptr 独占资源所有权 std::cout << *ptr << std::endl; // 输出 42 return 0; } ``` `create_int` 函数返回的 `unique_ptr` 通过移动语义将资源所有权转移给调用方[^1][^3]。 --- #### 2. 容器管理动态对象 在容器(如 `vector`)中存储动态分配的对象时,使用 `unique_ptr` 可自动释放内存。 ```cpp #include <vector> #include <memory> int main() { std::vector<std::unique_ptr<int>> vec; vec.push_back(std::make_unique<int>(10)); // 移动构造插入容器 vec.push_back(std::make_unique<int>(20)); // 容器销毁时,所有元素自动释放内存 return 0; } ``` 容器通过 `unique_ptr` 管理动态对象,避免手动释放内存的复杂性[^1][^3]。 --- #### 3. 管理动态数组 `unique_ptr` 支持动态数组的自动释放,避免使用 `new[]`/`delete[]`。 ```cpp #include <memory> int main() { auto arr = std::make_unique<int[]>(5); // 管理 int[5] 数组 arr[0] = 1; arr[1] = 2; // 超出作用域时自动调用 delete[] return 0; } ``` `unique_ptr<int[]>` 专为数组设计,提供下标访问功能[^3]。 --- #### 4. 实现工厂模式 工厂方法通过 `unique_ptr` 返回对象,确保调用方独占资源。 ```cpp class Shape { public: virtual void draw() = 0; virtual ~Shape() = default; }; class Circle : public Shape { public: void draw() override { std::cout << "Drawing Circle\n"; } }; std::unique_ptr<Shape> create_shape() { return std::make_unique<Circle>(); // 返回派生类对象 } int main() { auto shape = create_shape(); shape->draw(); // 输出 "Drawing Circle" return 0; } ``` 工厂方法通过基类 `unique_ptr` 返回多态对象,简化资源管理[^3][^4]。 --- #### 5. 实现资源所有权转移 通过 `std::move` 显式转移资源所有权,避免拷贝。 ```cpp #include <memory> void process(std::unique_ptr<int> ptr) { std::cout << "Processing: " << *ptr << std::endl; } int main() { auto ptr = std::make_unique<int>(100); process(std::move(ptr)); // 转移所有权到函数内 // 此时 ptr 已为空,无法再访问资源 return 0; } ``` 所有权转移后,原指针自动置空,防止悬空指针问题[^3][^4]。 --- ### 总结 `unique_ptr` 的核心价值在于: 1. **独占所有权**:确保资源仅被一个指针管理。 2. **自动释放**:离开作用域时自动释放资源。 3. **异常安全**:即使发生异常,资源也能正确释放。 4. **移动语义**:支持高效的资源所有权转移。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小马敲马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值