• C++11 shared_ptr unique_ptr weak_ptr


    1、shared_ptr(共享式内存)

    普通对象自定义deleter:

    错误用法(自定义deleter时不能使用make_shared<>())

    1. std::shared_ptr p_str = std::make_shared("name",
    2. [](std::string *str) {
    3. std::cout << "delete: " << str << std::endl;
    4. delete str;
    5. });

    正确用法

    1. std::shared_ptr p_str(new std::string("name"),
    2. [](std::string *str) {
    3. std::cout << "delete: " << *str << std::endl;
    4. delete str;
    5. });

    数组对象自定义deleter

    std::default_delete只针对单个类对象,因此如果是数组,则需要指定deleter

    1. // 使用自定义deleter
    2. std::shared_ptr<int> p_arr(new int[10],
    3. [](int *arr) {
    4. std::cout << "delete array."<< std::endl;
    5. delete []arr;
    6. });
    7. // 使用缺省deleter
    8. std::shared_ptr<int> p_arr_a(new int[10], std::default_delete<int []>());

    weak_ptr

    是 shared_ptr的帮手,用来共享对象但不拥有对象,它的use_count返回的是shared_ptr拥有的次数

    可以解决类之间互相引用,而导致两者都不会被析构的场景

    1. std::shared_ptr p_str_a = std::make_shared("nana");
    2. std::weak_ptr p_str_w1 = p_str_a;
    3. std::cout << "A expired:" << p_str_w1.expired() << std::endl;
    4. std::cout << "A use_count:" << p_str_w1.use_count() << std::endl;
    5. std::shared_ptr p_str_a2 = p_str_a;
    6. std::cout << "A expired:" << p_str_w1.expired() << std::endl;
    7. std::cout << "A use_count:" << p_str_w1.use_count() << std::endl;
    8. p_str_a.reset();
    9. p_str_a2.reset();
    10. std::cout << "B expired:" << p_str_w1.expired() << std::endl;
    11. std::cout << "B use_count:" << p_str_w1.use_count() << std::endl;

    重复析构

    初始指针只能赋值一次给shared_ptr,之后的shared_ptr的初始化只能由其它shared_ptr初始化,防止重复析构。

    错误示例:

    1. int *p_i = new int;
    2. std::shared_ptr<int> sp1_i(p_i);
    3. std::shared_ptr<int> sp2_i(p_i); // ERROR!!! 会产生两次析构

    正确用法:

    1. int *p_i = new int;
    2. std::shared_ptr<int> sp1_i(p_i);
    3. std::shared_ptr<int> sp2_i(sp1_i);

    enable_shared_from_this

    为了解决对象内this指针多次被shared_ptr类声明时需要使用

    示例:

    1. Class Data: std::enable_shared_from_this {
    2. std::shared get_share_ptr() {
    3. return std::shared_from_this();
    4. }
    5. }

    类内使用 std::shared_from_this()函数即可获得this的shared_ptr。

    强制转换为普通指针

    1. std::shared_ptr<void> sp(new int);
    2. std::static_pointer_cast<int *>(sp);

    线程安全

    1. // std::shared_ptr g_int;
    2. // {
    3. // std::shared_ptr local_int = std::make_shared(10);
    4. // std::atomic_store(&g_int, local_int);
    5. // }

    2、unique_ptr(独占式内存)

    初始化

    1. // 不允许复制语法赋初值
    2. // std::unique_ptr tmp_i = new int; // ERROR
    3. std::unique_ptr<int> tmp_i(new int); // OK

    重置赋值

    1. std::unique_ptr<int> uptr;
    2. uptr.reset(new int); // 重置赋值

    释放使用权

        uptr.release(); // 释放使用权 uptr.reset() 或 uptr = nullptr;

    安全判断

    1. //方法1:
    2. if (uptr) {
    3. std::cout << "uptr = " << *uptr << std::endl;
    4. }
    5. //方法2: if (uptr != nullptr)
    6. //方法3: if (uptr.get() != nullptr)

    拷贝(值传递)

    1. std::unique_ptr<int> up1(new int);
    2. // std::unique_ptr up2(up1); // ERROR
    3. std::unique_ptr<int> up2(std::move(up1));

    unique_ptr作为函数参数:调用者必须手动调用std::move()

    unique_ptr作为函数返回值:C++ 11编译器规定return语句不需要显式的调用std::move(),会自动调用std::move()

    unique_ptr的偏特化:数组

    数组初始化

    std::unique_ptr up_str(new std::string[10]);

    定义deleter

    1. // 错误
    2. // std::unique_ptr p_arr1(new int[10],
    3. // [](int *arr) {
    4. // std::cout << "delete array."<< std::endl;
    5. // delete []arr;
    6. // });
    7. // 正确方法1
    8. std::unique_ptr<int,void(*)(int*)> p_arr2(new int[10],
    9. [](int *arr) {
    10. std::cout << "delete array2."<< std::endl;
    11. delete []arr;
    12. });
    13. // 正确方法2
    14. std::unique_ptr<int,std::function<void(int*)>> p_arr3(new int[10],
    15. [](int *arr) {
    16. std::cout << "delete array2."<< std::endl;
    17. delete []arr;
    18. });
    19. // 方法3
    20. auto fun_del = [](int *arr) {
    21. std::cout << "delete array2."<< std::endl;
    22. delete []arr;
    23. };
    24. // 方法4 利用alias
    25. using unique_ptr_int = std::unique_ptr<int, void(*)(int*)>;
    26. unique_ptr_int up_aa(new int[10], [](int *arr) {
    27. std::cout << "delete array2."<< std::endl;
    28. delete []arr;
    29. });

    deleter深度挖掘

    对于deleter,除了内存上的释放,还可以析构其它资源(如:文件句柄、socket句柄、共享内存等等)

    示例如下:析构文件

    1. std::unique_ptrvoid(*)(std::ofstream*)> p_ofs(new std::ofstream("text.txt"),
    2. [](std::ofstream *ofs) {
    3. std::cout << "delete ofstream" << std::endl;
    4. ofs->close();
    5. delete ofs;
    6. });

  • 相关阅读:
    持续集成(二)Jenkins基本使用介绍
    100天精通Oracle-实战系列(第21天)Oracle 数据泵常用参数和命令
    virualBox虚拟机系统磁盘fdisk无损扩容
    Gif格式图片怎么制作?超简单的方法分享
    搭建本地私有仓库
    Java中级面试题及答案(120道Java中级面试题大汇总)
    【leetcode】287. 寻找重复数
    IO流的学习1
    如何批量上传Maven仓库jar包到Nexus3.x私服
    硬件总线基础07:PCIe总线基础-事务层(1)
  • 原文地址:https://blog.csdn.net/Kernel_Heart/article/details/126362972