C++11 shared_ptr unique_ptr weak_ptr

1、shared_ptr(共享式内存)

普通对象自定义deleter:

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

std::shared_ptr<std::string> p_str = std::make_shared<std::string>("name", 
                        [](std::string *str) {
                            std::cout << "delete: " << str << std::endl;
                            delete str;
                    });

正确用法

    std::shared_ptr<std::string> p_str(new std::string("name"), 
                                        [](std::string *str) {
                                            std::cout << "delete: " << *str << std::endl;
                                            delete str;
                                        });

数组对象自定义deleter

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

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

weak_ptr

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

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

    std::shared_ptr<std::string> p_str_a = std::make_shared<std::string>("nana");
    std::weak_ptr<std::string> p_str_w1 = p_str_a;
    std::cout << "A expired:" << p_str_w1.expired() << std::endl;
    std::cout << "A use_count:" << p_str_w1.use_count() << std::endl;
    std::shared_ptr<std::string> p_str_a2 = p_str_a;
    std::cout << "A expired:" << p_str_w1.expired() << std::endl;
    std::cout << "A use_count:" << p_str_w1.use_count() << std::endl;
    p_str_a.reset();
    p_str_a2.reset();
    std::cout << "B expired:" << p_str_w1.expired() << std::endl;
    std::cout << "B use_count:" << p_str_w1.use_count() << std::endl;

重复析构

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

错误示例:

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

正确用法:

    int *p_i = new int;
    std::shared_ptr<int> sp1_i(p_i);
    std::shared_ptr<int> sp2_i(sp1_i);

enable_shared_from_this

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

示例:

Class Data: std::enable_shared_from_this<Data> {

    std::shared<Data> get_share_ptr() {

        return std::shared_from_this();
    }
}

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

强制转换为普通指针

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

线程安全

    // std::shared_ptr<int> g_int;
    // {
    //     std::shared_ptr<int> local_int = std::make_shared<int>(10);
    //     std::atomic_store(&g_int, local_int);
    // }

2、unique_ptr(独占式内存)

初始化

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

重置赋值

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

释放使用权

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

安全判断

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

拷贝(值传递)

    std::unique_ptr<int> up1(new int);
    // std::unique_ptr<int> up2(up1); // ERROR
    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<std::string[]> up_str(new std::string[10]);

定义deleter

    // 错误
    // std::unique_ptr<int> p_arr1(new int[10], 
    //                             [](int *arr) {
    //                                 std::cout << "delete array."<< std::endl;
    //                                 delete []arr;
    //                             });
    // 正确方法1
    std::unique_ptr<int,void(*)(int*)> p_arr2(new int[10], 
                                [](int *arr) {
                                    std::cout << "delete array2."<< std::endl;
                                    delete []arr;
                                });
    // 正确方法2
    std::unique_ptr<int,std::function<void(int*)>> p_arr3(new int[10], 
                                [](int *arr) {
                                    std::cout << "delete array2."<< std::endl;
                                    delete []arr;
                                });
    // 方法3
    auto fun_del = [](int *arr) {
                        std::cout << "delete array2."<< std::endl;
                        delete []arr;
                    };
    // 方法4 利用alias
    using unique_ptr_int = std::unique_ptr<int, void(*)(int*)>;
    unique_ptr_int up_aa(new int[10], [](int *arr) {
                                    std::cout << "delete array2."<< std::endl;
                                    delete []arr;
                                });

deleter深度挖掘

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

示例如下:析构文件

    std::unique_ptr<std::ofstream, void(*)(std::ofstream*)> p_ofs(new std::ofstream("text.txt"),
                                                                  [](std::ofstream *ofs) {
                                                                        std::cout << "delete ofstream" << std::endl;
                                                                        ofs->close();
                                                                        delete ofs;
                                                                  });

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值