C++智能指针之unique_ptr(保姆级教学)

目录

unique_ptr

概述

涉及程序

初始化

手动初始化

std::make_unique函数(C++14)

unique_ptr常规操作

不支持操作:该指针不支持拷贝和赋值操作;所以不能拷贝到容器里

移动语义std::move();

release();

reset();

*解应用

get();

指定删除器

unique_ptr和shared_ptr指定删除器时的区别

unique_ptr尺寸


unique_ptr

概述

独占式指针(专属所有权),同一时刻,只能有一个unique_ptr指向这个对象;当指针销毁,指向的对象也销毁;因此该指针不支持拷贝和赋值操作,也不存在引用计数。

涉及程序

#include <iostream>
#include <memory>
#include <vector>
using namespace std;

class A
{
public:
    A()
    {
        cout << "A" << endl;
    }

    A(int num) : m_num(num)
    {
        cout << "A int" << endl;
    }

    A(const A &&other) : m_num(other.m_num)
    {
        cout << "A move int" << endl;
    }

    ~A()
    {
        cout << "~A" << endl;
    }

public:
    int m_num;
};

void mydelete(A *p)
{
    delete[] p;
}
int main(int argc, char const *argv[])
{
#if 0
    unique_ptr<int> p(new int(5));            //可以指定删除器
    unique_ptr<int> p2 = make_unique<int>(6); //不可用指定删除器
    // unique_ptr<int>p2 = p;

    //指定删除器
    // unique_ptr<A[]>pa(new A[3]);
    using p_delete = void (*)(A * p);
    unique_ptr<A, p_delete> pa(new A[3], mydelete);
    unique_ptr<A>ptr(new A());

    vector<unique_ptr<A>>vp;
    // vp.push_back(pa);
    // vp.push_back(ptr);

    cout << sizeof(pa) <<endl;
    cout << sizeof(ptr) <<endl;

    // shared_ptr<A> pa(new A[3], mydelete);
    // shared_ptr<A> ptr(new A(5));
    // vector<shared_ptr<A>>vp;
    // vp.push_back(pa);
    // vp.push_back(ptr);

//release():放弃智能指针的控制权,将该指针置为nullptr,返回的是裸指针
    unique_ptr<int>pi(new int(5));
    int *temp = pi.release();
    if(pi = nullptr)
    {
        cout <<"pi is nullptr"<<endl;
    }
    cout << *temp<<endl;
//reset() reset(参数)
    unique_ptr<int>p2(new int(5));
    p2.reset();
    p2.reset(new int(6));
    cout << *p2<<endl;
#endif
    //移动语义std::move()
    unique_ptr<A> ptr(new A(5));
    unique_ptr<A> &&rptr = std::move(ptr);
    cout << ptr->m_num <<endl;
    cout << rptr->m_num <<endl;
    
    return 0;
}

初始化

手动初始化

unique_ptr p;或unique p(new int(5))

std::make_unique函数(C++14)

注:生成的指针不支持指定删除器语法

unique_ptr常规操作

不支持操作:该指针不支持拷贝和赋值操作;所以不能拷贝到容器里

不支持拷贝:

不支持赋值:

无法拷贝到容器

移动语义std::move();

使用右值引用可以进行赋值

release();

放弃对指针的控制权,将该指针置nullptr,返回裸指针;

注:返回的裸指针手动释放(防止内存泄漏)或者可以初始化另一个指针

reset();

  • reset()无参使用:若该智能指针是独占某个对象,则释放该对象,并将智能指针置nullptr;
  • reset()代参使用:若该智能指针是独占某个对象,则释放该对象,并将该指针指向新对象;

实例:p.reset();p.reset(new int());

*解应用

获得智能指针指向的对象,并对其操作;

get();

考虑到有些函数参数是裸指针并不是智能指针,所以需要将智能指针转化为裸指针;

获得智能指针中保存的指针(裸指针);

注:获得裸指针要小心使用,因为智能指针一旦释放,裸指针也就失效;

指定删除器

语法:unique_ptr 智能指针变量名

以下图为例,当指针指向一段连续的数组空间时,会产生内存泄漏

一般的解决办法是指定数组(加“[ ]”)

自定义删除函数

unique_ptr的删除器需要我们指定删除器的类型,当我们像shared_ptr一样直接传入删除器就会产生报错,如下图所示:

指定删除器类型操作如下图所示,运行结果正常

注:unique_ptr的删除器类型可以任意定义,而shared_ptr的删除器类型必须是void类型

unique_ptr和shared_ptr指定删除器时的区别

区别1:unique_ptr在使用时必须要指定删除器的类型,而shared_ptr不需要指定

区别2:

  • 同类型的shared_ptr拥有不同的删除器,那么这些shared_ptr仍然是相同类型的

根据容器的特性,类型相同的变量可以存放在同一个容器中,我们使用vector容器成功验证了shared_ptr,如下图所示

  • 而指定不同删除器会导致不同类型的unique_ptr,因为unique_ptr的尺寸会发生变化

通过输出指针的大小,就可以发现不同删除器的unique_ptr的大小都不一样

但不能通过push_back插入到容器中的操作来验证,因为push_back是通过拷贝的操作将变量添加到容器中,而unique_ptr不支持拷贝操作

unique_ptr尺寸

unique_ptr的尺寸和裸指针一样大,但是指定自定义删除函数会影响尺寸大小;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

竹烟淮雨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值