shared_ptr的详解

参考:《C++ primer 第五版》

                https://www.cnblogs.com/boydfd/p/5146432.html (需要多看几遍)

前言

程序中常用的存储形式如下。

静态内存:static对象,类static的数据成员,函数外的变量。

栈内存:函数内的非static对象。

自由空间或堆:动态分配的对象,程序控制生命周期。

动态内存与智能指针

从前,我们使用运算符new和delete来管理动态内存。但是使用很容易出错误,造成泄露。

新标准提供两个智能指针,shared_ptr和unique_ptr,来自动释放管理的动态对象。前者可以多个指针指向同一个对象,后者独占对象。另外还有weak_ptr,是一个伴随类,弱引用,指向shared_ptr管理的对象。

常见的用法(我们注意其中的get(),我觉得智能指针,并不是指针可以看作是指针的管理器):

shared_ptr的详解_第1张图片


shared_ptr

make_shared,这是最安全的分配使用方式,他是使用参数的构造函数来生成对像,也就是参数必须符合构造函数的参数表。我们通常使用auto来保存他返回的结果。

shared_ptr会记录有多少个shared_ptr指向同一个对象,当我们拷贝或者赋值一个shared_ptr时,计数器加一,被销毁则减一,为0则释放内存(析构函数)。

shared_ptr和new的结合使用

它的构造函数是explicit的,内置指针不能隐式的转换为智能指针,只能使用初始化的形式。

   shared_ptr p1 = new int(11);   //错误,必须使用直接初始化形式
   shared_ptr p2( new int(11) );   //正确,使用直接初始化
   shared_ptr p3 = shared_ptr( new int(12) ); //同上

不要混合使用普通指针和智能指针

   void process( shared_ptr ptr )
   {

   } //离开,ptr被销毁

    //显式的,正确的
    shared_ptr p(new int(42));
    process(p);
    int i =*p;

    //临时的shared_ptr,错误的
    int *x( new int(1024) );
    process(x); //错误,不能转化
    process( shared_ptr(x) );  //x在这里被释放掉
    int j = *x;  //错误,这里是一个空悬指针

不要使用get来初始化另一个智能指针或为智能指针赋值

   shared_ptr p( new int(42) );  //引用计数为1
    int *q = p.get();   //正确,我们不可以使用delete释放q
    {
        shared_ptr (q); //和p指向了同一个地址, 这里的计数还是1
    } //程序块结束, q被销毁, 指向的内存被释放
    int foo = *p; //非法的指针,为空悬指针

如果使用的智能指针管理的不是new分配的内存(或者说delete无法释放的内存)那么我们定义一个删除器函数完成对其的释放工作。

shared_ptr p( &c, end_yourtype ) //end_yourtype为删除器,无论正常退出或异常都会释放

unique_ptr
某一时刻只能有一个unique_ptr指向一个给定的对象。下表列出它特有的操作,相同的在第一个表中。

shared_ptr的详解_第2张图片

我们不能拷贝或复制unique_ptr,但是可以使用release()和reset()转交给另一个unique。

重载unique_ptr中删除器时,必须在<>中提供删除器的类型。

在C++14中,已经支持make_unique<>()方法。可以参考make_shared,但是make_都不支持添加删除器,或者初始化列表。

 auto b = make_shared>({1,2,3}); // 错误

weak_ptr,是一种不控制所指向对象生存周期的智能指针,指向一个shared_ptr管理的对象,他不会增加引用计数。常用操作:

shared_ptr的详解_第3张图片

我们使用lock()来判断是否为空,他是为了解决循环引用的问题。

#include
#include

using namespace std;
class B;
class A
{
public:// 为了省去一些步骤这里 数据成员也声明为public
//    weak_ptr pb;
    shared_ptr pb;
    void doSomthing()
    {
//        if(pb.lock())
//        {
//
//        }
    }

    ~A()
    {
        cout << "kill A\n";
    }
};

class B
{
public:
//        weak_ptr pa;
        shared_ptr pa;
    ~B()
    {
        cout <<"kill B\n";
    }
};

int main()
{
    shared_ptr sa(new A());
    shared_ptr sb(new B());
    if(sa && sb)
    {
        sa->pb=sb;
        sb->pa=sa;
    }

    cout<<"sa use count:"<
如果使用shared_ptr,结果为2,并且不会调用析构函数(不输出kill).

你可能感兴趣的:(C/C++)