unique_ptr的详细介绍

unique_ptr 的详细介绍及典型使用场景的测试用例:


1. unique_ptr 核心特性

  • 独占所有权:同一时刻只有一个 unique_ptr 拥有对象所有权
  • 不可复制(但可移动):禁止拷贝构造和拷贝赋值,避免意外的所有权共享
  • 零开销:与裸指针相比,无额外内存或性能开销(编译器优化后)
  • 自动释放:离开作用域时自动释放资源,保证异常安全

2. 基本用法测试用例

(1) 创建与释放
#include <memory>
#include <iostream>

class MyResource {
public:
    MyResource() { std::cout << "资源创建\n"; }
    ~MyResource() { std::cout << "资源释放\n"; }
    void use() { std::cout << "使用资源\n"; }
};

int main() {
    // 创建 unique_ptr(推荐使用 C++14 的 make_unique)
    std::unique_ptr<MyResource> ptr = std::make_unique<MyResource>();
    ptr->use();

    // 显式释放资源(可选)
    ptr.reset(); // 输出 "资源释放"
    return 0;
}

输出结果

资源创建
使用资源
资源释放

(2) 所有权转移
void transferOwnership(std::unique_ptr<MyResource> newOwner) {
    newOwner->use();
} // 函数结束时释放资源

int main() {
    std::unique_ptr<MyResource> owner = std::make_unique<MyResource>();
    
    // 转移所有权(移动语义)
    transferOwnership(std::move(owner)); 
    
    // 此时 owner 变为空指针
    if (!owner) {
        std::cout << "所有权已转移\n";
    }
    return 0;
}

输出结果

资源创建
使用资源
资源释放
所有权已转移

3. 高级用法测试用例

(1) 管理数组
#include <memory>
#include <iostream>
int main() {
    // 管理动态数组(自动调用 delete[])
    std::unique_ptr<int[]> arr = std::make_unique<int[]>(5);
    for (int i = 0; i < 5; ++i) {
        arr[i] = i * 10;
    }

    // 输出数组内容
    for (int i = 0; i < 5; ++i) {
        std::cout << arr[i] << " ";
    }
    return 0;
}

输出结果

0 10 20 30 40

(2) 自定义删除器
#include <cstdio>
#include <memory>
#include <iostream>
// 自定义文件句柄释放逻辑
struct FileDeleter {
    void operator()(FILE* file) const {
        if (file) {
            std::fclose(file);
            std::cout << "文件已关闭\n";
        }
    }
};

int main() {
    // 使用自定义删除器管理文件
    std::unique_ptr<FILE, FileDeleter> filePtr(
        std::fopen("test.txt", "w"), 
        FileDeleter{}
    );

    if (filePtr) {
        std::fputs("Hello unique_ptr", filePtr.get());
    }
    return 0;
}

输出结果

文件已关闭

(3) 作为函数返回值
#include <memory>
#include <iostream>

class MyResource {
public:
    MyResource() { std::cout << "资源创建\n"; }
    ~MyResource() { std::cout << "资源释放\n"; }
    void use() { std::cout << "使用资源\n"; }
};
std::unique_ptr<MyResource> createResource() {
    return std::make_unique<MyResource>();
}

int main() {
    auto res = createResource();
    res->use();
    return 0;
}

输出结果

资源创建
使用资源
资源释放

4. 常见错误规避

(1) 禁止拷贝操作
std::unique_ptr<MyResource> ptr1 = std::make_unique<MyResource>();
std::unique_ptr<MyResource> ptr2 = ptr1; // 编译错误!
(2) 正确释放后访问
auto ptr = std::make_unique<MyResource>();
ptr.reset(); // 释放资源
ptr->use();  // 未定义行为(程序可能崩溃)

5. unique_ptrshared_ptr 对比

特性unique_ptrshared_ptr
所有权独占共享
性能开销引用计数原子操作
拷贝语义禁止(仅移动)允许
典型场景工厂模式、资源独占管理多对象共享资源

6. 最佳实践总结

  • 优先使用 make_unique(C++14+):避免显式 new,保证异常安全
  • 明确所有权转移:通过 std::move 传递所有权
  • 避免与裸指针混用:不直接暴露 get() 获得的指针
  • 自定义删除器:灵活管理非内存资源(文件、网络连接等)

通过合理使用 unique_ptr,可以显著提高代码的 资源安全性可维护性

<think>好的,我现在需要帮助用户了解C++中的unique_ptr智能指针。根据用户的问题,他们想要详细介绍、示例代码、使用方法以及官方文档的信息。首先,我应该回忆一下unique_ptr的基本概念和特性。 unique_ptrC++11引入的智能指针,用于独占管理动态分配的对象,确保同一时间只有一个unique_ptr指向该对象。这一点和shared_ptr不同,后者允许多个指针共享所有权。我记得unique_ptr不能被复制,只能通过移动转移所有权,这样可以避免资源的多重释放,提高安全性。 接下来,用户需要示例代码。我需要提供几个典型的用例,比如创建unique_ptr、转移所有权、自定义删除器等。例如,用new初始化unique_ptr,然后用std::move转移所有权。还要展示如何释放所有权和使用get()方法获取原始指针。 然后,使用方法部分要说明何时使用unique_ptr,比如管理独占资源、作为函数返回值或参数传递。还需要提到它支持数组,但更推荐使用容器如std::vector或std::array。 关于官方文档,应该推荐用户参考C++标准库文档,比如cppreference.com,并提供链接。同时,可能需要注意不同C++版本的差异,比如C++14添加的make_unique函数。 还需要检查提供的引用内容。用户提供的引用[2]和[4]提到了unique_ptr与shared_ptr的区别,以及示例代码,可以引用这些内容来支持回答。例如,引用[2]说明unique_ptr独占对象,引用[4]展示了shared_ptr的用法,但需要指出unique_ptr的不同之处。 另外,要确保回答符合系统级指令,比如数学公式的正确格式,但在这个问题中可能用不上数学公式。需要检查LaTeX语法是否正确,但示例中没有涉及数学表达式,所以可能没问题。 需要生成相关问题,可能包括unique_ptr与shared_ptr的区别、如何转移所有权、自定义删除器的使用等。这些问题应该与用户的问题相关,并帮助进一步学习。 最后,确保回答结构清晰,分点介绍,示例代码用代码块格式,引用正确标注。比如在介绍独占性时引用[2],在示例代码部分引用[4]中的相关概念。 总结步骤:介绍unique_ptr的特性,提供多个示例代码,说明使用方法,引用相关文献,生成相关问题,并确保格式正确。</think>### C++ unique_ptr 详细介绍 #### 一、核心特性 1. **独占所有权** `unique_ptr` 是C++11引入的智能指针,严格遵循**单一所有权**模型,确保同一时刻只有一个指针拥有对象的控制权[^2]。 示例: ```cpp std::unique_ptr<int> ptr1(new int(42)); // 创建独占指针 // std::unique_ptr<int> ptr2 = ptr1; // 错误!无法复制 std::unique_ptr<int> ptr2 = std::move(ptr1); // 正确:通过移动转移所有权 ``` 2. **自动释放资源** 当 `unique_ptr` 离开作用域时,会自动调用析构函数释放资源,无需手动 `delete`。 3. **支持自定义删除器** 可通过模板参数指定自定义删除逻辑(如文件句柄、网络连接等): ```cpp auto FileDeleter = [](FILE* fp) { if (fp) fclose(fp); }; std::unique_ptr<FILE, decltype(FileDeleter)> filePtr(fopen("test.txt", "r"), FileDeleter); ``` --- #### 二、示例代码 1. **基础用法** ```cpp #include <memory> #include <iostream> class MyClass { public: MyClass() { std::cout << "Created\n"; } ~MyClass() { std::cout << "Destroyed\n"; } }; int main() { std::unique_ptr<MyClass> ptr(new MyClass()); // 创建对象 if (ptr) { // 检查是否为空 ptr->doSomething(); // 调用成员函数 } return 0; // 自动释放资源 } ``` 2. **数组管理(C++11/14)** ```cpp // C++11方式 std::unique_ptr<int[]> arr(new int[5]{1,2,3,4,5}); // C++14推荐方式 auto arr = std::make_unique<int[]>(5); ``` 3. **所有权转移** ```cpp std::unique_ptr<std::string> createString() { return std::make_unique<std::string>("Hello"); } int main() { auto strPtr = createString(); // 所有权从函数转移到主函数 std::cout << *strPtr; // 输出: Hello return 0; } ``` --- #### 三、关键方法 | 方法 | 功能描述 | |----------------------|---------------------------------| | `reset()` | 释放当前对象并接管新指针(可空) | | `release()` | 放弃所有权,返回原始指针(需手动管理) | | `get()` | 获取原始指针(不转移所有权) | | `swap()` | 交换两个 `unique_ptr` 的所有权 | --- #### 四、最佳实践 1. **优先使用 `std::make_unique`**(C++14起支持)[^4]: ```cpp auto ptr = std::make_unique<MyClass>(); // 避免显式new,更安全 ``` 2. **避免混合使用原始指针**: ```cpp MyClass* rawPtr = ptr.get(); // 严禁 delete rawPtr 或转移所有权到其他智能指针 ``` 3. **作为函数参数传递时**: - 若函数需要接管所有权:使用 `std::unique_ptr<T>&&` 或按值传递 - 若仅需访问对象:使用 `T*` 或 `T&` --- #### 五、官方文档 - **C++标准库文档**: [cppreference.com - unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr) - **微软MSDN**: [unique_ptr Class](https://docs.microsoft.com/en-us/cpp/standard-library/unique-ptr-class) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值