智能指针(四) unique_ptr

25 篇文章 1 订阅

智能指针(四) unique_ptr

unique_ptr 的初始化

  • unique_ptr的初始化(和shared_ptr的初始化相同)
// todo 使用 new int
    void func()
    {
        unique_ptr<int> pi;
        if (pi == nullptr)
        {
            cout << "pi is null" << endl;
        }
        unique_ptr<int> pi2(new int);
        if (pi2)
        {
            cout << "pi2 is 初始化ed" << endl;
        }
    }
//  todo 使用 make_unique
    void func2()
    {
        unique_ptr<int> pi = make_unique<int>(100);
        auto p2 = make_unique<int>(100);
        if (pi && p2)
        {

            cout << "pi and p2 is 初始化ed" << endl;
        }
    }

unique_ptr不支持的操作

  • 独占式指针,该智能指针不支持拷贝动作(定义时初始化)
 void func()
    {

        auto i = make_unique<int>(100);
        // auto i2(i); // INFO unique_ptr是独占式指针,该智能指针不支持拷贝动作(定义时初始化)
        // unique_ptr<int> i2(i);
        // unique_ptr<int> i3 =i ;  // INFO 智能指针不支持 赋值动作
    }

移动语义

 void func()
    {
        unique_ptr<int> i = make_unique<int>(100);
        // auto i2=(i);//不允许
        auto i2 = std::move(i); // todo 可以转交 控制权
        if (nullptr != i2 && nullptr == i)
        {
            cout << "i指针置空,i2指向i 原来所指向对象" << std::endl;
        }
    }

release()

  • release() 放对指针的控制权(切断了智能指针和其所指向的对象之间的联系)

  • 返回裸指针,将该智能指针置空。返回的这个裸指针我们可以手工delete来释放,

  • 也可以用来初始化另外一个智能指针(shared_ptr的get则不可以),

  • release()并不释放内存,仅仅只是将std::unique_ptr中的数据指针置空并抛出数据指针;

 void func()
    {

        unique_ptr<int> ui = make_unique<int>(100);
        // 初始化 另一个 智能指针
        auto i = ui.release();
        if (nullptr != i && nullptr == ui)
        {
            cout << "ui指针置空,i指向ui 原来所指向对象" << std::endl;
        }
    }
    void func2()
    {
        unique_ptr<int> ui = make_unique<int>(100);

        int *i = ui.release();
        delete i; // 返回的  裸指针可以主动delete
        if (nullptr == i && nullptr == ui)
        {
            cout << "ui 和 i 指针 指向空" << std::endl;
        }
    }

reset()

不带参数

  • reset()不带参数情况:释放智能指针所指向的对象,并将智能指针置空。会释放内存
void func()
    {
        unique_ptr<string> ps1(new string("I Love Chinal !"));
        ps1.reset();
        if (ps1 = nullptr)
        {
            cout << "psl被置空" << endl;
        }
    }

带参数

  • 带参数的情况,释放智能指针所指向的对象,并让该智能指针指向新对象
void func2()
    {
        unique_ptr<string> ps1(new string("I Love Chinal !"));

        unique_ptr<string> ps2(new string("I Love Chinal too!"));

        cout << "*ps2:: " << *ps2 << endl;
        ps1.reset(ps2.release()); // todo 释放了 ps2 指针,并让 ps1 指向 ps2 原先指向的内存
        cout << "*ps1:: " << *ps1 << endl;
    }

release和 reset 源码比较

另外在std::unique_ptr中有两个成员函数,比较容易混淆,即

    pointer release() noexcept {
        return _STD exchange(_Mypair._Myval2, nullptr);
    }

    void reset(pointer _Ptr = nullptr) noexcept {
        pointer _Old = _STD exchange(_Mypair._Myval2, _Ptr);
        if (_Old) {
            _Mypair._Get_first()(_Old);
        }
    }

从上面的源码中,可以看出,release()并不释放内存,仅仅只是将std::unique_ptr中的数据指针置空并抛出数据指针;而reset(pointer _Ptr = nullptr)会调用析构函数,释放内存。

nullptr

  • nullptr() 释放智能带针所指向的对象,并将智能指针置空*

    // 不演示

指向一个数组

 void func()
    {
        unique_ptr<int[]> ps1(new int[10]); // todo 数组这里要跟上[]
        for (auto i = 0; i < 10; i++)
        {
            ps1[i] = i;
        }
        for (auto i = 0; i < 10; i++)
        {
            cout << "ps1[" << i << "]" << ps1[i] << endl;
        }
    }

swap()

  • 交换智能指针指向的对象(和shared_ptr相同)

    // 不演示

unique_ptr 转换为 shared_ptr

  • 如果unique]ptr为右值,就可以将它赋值给shared_ptr
  • 因为shared ptr包含一个显式构造函数,可用于将右值unqiue_ptr转换为shared ptr
 void func()
    {

        unique_ptr<int> ui = make_unique<int>(100);
        shared_ptr<int> si = (std::move(ui));
        cout << "si.get():: " << *si << endl;
    }

shared_pre 注意点

unique_ptr 支持拷贝

  • 虽然unique ptr智能指针不能拷贝,但是,当这个unique_ptr将要被销毁,是可以拷贝的。最常见用法就是从函数返回
namespace detail
{
    unique_ptr<int> func(int nums)
    {
        return std::unique_ptr<int>(new int(nums));
    }
}

 auto i = detail::func(150);
    cout << "i:  " << *i << endl;

指定删除器(和shared_ptr不同)

  • 格式:unique_ptr<指向的对象类型,删除器函数类型>智能指针变量名:
 void mydelter(string *pdel)
    {
        cout << "mydelter is called" << endl;
        delete pdel;
        pdel = nullptr;
    };
    void func()
    {
        using T = void (*)(string *);

        // unique_ptr<string> ui (new string("mydelter")); //调用默认删除器
        unique_ptr<string, T> ui(new string("mydelter"), mydelter);
    }

删除器决定对象类型

作为容器元素存储在容器中

namespace detail3
{

    void mydelter(string *pdel)
    {
        cout << "detail3::mydelter is called" << endl;
        delete pdel;
        pdel = nullptr;
    };
    int mydelter2(string *pdel)
    {
        cout << "detail3::mydelter2 is called" << endl;
        delete pdel;
        pdel = nullptr;
        return 0;
    };
    void func()
    {
        using T = void (*)(string *);

        using T2 = int (*)(string *);
        unique_ptr<string> ui1(new string("mydelter")); // 调用默认删除器
        unique_ptr<string, T> ui2(new string("mydelter"), mydelter);
        unique_ptr<string, T2> ui3(new string("mydelter"), mydelter2);

        vector<unique_ptr<string>> vs;
        vs.push_back(std::move(ui1));
        // vs.push_back(ui2); //error
        // vs.push_back(ui3); //error

        vector<unique_ptr<string, T>> vsT; // 自定义删除器的必须标明 自定义删除器函数类型
        vsT.push_back(std::move(ui2));
        // vsT.push_back(std::move(ui3)); // 删除器类型不同,  void mydelter(string *pdel)和  int mydelter2(string *pdel),是不同对象,所以不能放入容器中
    }
}

unique_ptr需要明确知道类型的析构函数

namespace detail4
{

    class TC; // 不提供析构函数

    void func()
    {

        // unique_ptr<TC> up;   // error: invalid application of 'sizeof' to incomplete type 'detail4::TC'
        shared_ptr<TC> tc; // shared_ptr可以正常运行
    }
}

参见 <shared_ptr和unique_ptr深入探秘>

需要明确知道类型的析构函数*

namespace detail4
{

    class TC; // 不提供析构函数

    void func()
    {

        // unique_ptr<TC> up;   // error: invalid application of 'sizeof' to incomplete type 'detail4::TC'
        shared_ptr<TC> tc; // shared_ptr可以正常运行
    }
}

参见 <shared_ptr和unique_ptr深入探秘>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

丁金金

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

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

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

打赏作者

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

抵扣说明:

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

余额充值