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 
#include 
#include 
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 p(new int(5));            //可以指定删除器
    unique_ptr p2 = make_unique(6); //不可用指定删除器
    // unique_ptrp2 = p;

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

    vector>vp;
    // vp.push_back(pa);
    // vp.push_back(ptr);

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

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

初始化

手动初始化

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

C++智能指针之unique_ptr(保姆级教学)_第1张图片

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

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

C++智能指针之unique_ptr(保姆级教学)_第2张图片

unique_ptr常规操作

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

不支持拷贝:

C++智能指针之unique_ptr(保姆级教学)_第3张图片

不支持赋值:

C++智能指针之unique_ptr(保姆级教学)_第4张图片

无法拷贝到容器

C++智能指针之unique_ptr(保姆级教学)_第5张图片

移动语义std::move();

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

C++智能指针之unique_ptr(保姆级教学)_第6张图片

release();

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

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

C++智能指针之unique_ptr(保姆级教学)_第7张图片

reset();

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

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

C++智能指针之unique_ptr(保姆级教学)_第8张图片

*解应用

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

get();

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

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

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

指定删除器

语法:unique_ptr 智能指针变量名

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

C++智能指针之unique_ptr(保姆级教学)_第9张图片

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

C++智能指针之unique_ptr(保姆级教学)_第10张图片

自定义删除函数

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

C++智能指针之unique_ptr(保姆级教学)_第11张图片

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

C++智能指针之unique_ptr(保姆级教学)_第12张图片

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

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

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

区别2:

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

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

C++智能指针之unique_ptr(保姆级教学)_第13张图片

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

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

C++智能指针之unique_ptr(保姆级教学)_第14张图片

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

C++智能指针之unique_ptr(保姆级教学)_第15张图片

unique_ptr尺寸

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

C++智能指针之unique_ptr(保姆级教学)_第16张图片

你可能感兴趣的:(C/C++内存管理精讲,c++,嵌入式,C/C++,智能指针)