RAII

问题:
申请资源
使用
释放资源 ---- 通常遗忘 --- 内存泄漏 fd

使用对象的自动析构的方式,进行所申请资源的自动释放

auto_ptr

禁止隐式构造
允许拷贝构造
允许等号运算符

不能让多个智能指针指向同一块空间

不能用auto_ptr直接传参,否则会直接崩溃
传引用可以

显式构造带有类型
隐式的不带类型

    int* p1 = new int(100);
    //auto_ptr<int> p2 = auto_ptr<int>(p1);  显式
    //auto_ptr<int> p2 = p1;隐式
    auto_ptr<int>p2(p1);//显式
    auto_ptr<int> p3(new int(10));

    //p2 = p3;  //此时把p3指针放入p2,p3指针不存在,所以解引用p3会崩溃
//p2开始存p1指针,接收p3后,p1被释放掉,所以p1无效
//
//cout << *p1 << endl;//无效 、//解引用p1 //cout << *p2 << endl;//10 //cout << *p3 << endl;//崩溃 //auto_ptr<int> p4 = p2; //cout << *p1 << endl; //cout << *p2 << endl; //cout << *p3 << endl;
   //获取指针
    int* tmp1 = p2.get();
    cout << *tmp1 << endl;

    //转移
    int* tmp2 = p2.release();
    //cout << *p2 << endl;//崩溃

    p2.reset(p1);
    //重置自身   干掉自身本来的指针,获取新的指针



    vector<auto_ptr<int>> v;


    //auto_ptr 不能使用容器
    //加入容器的过程是等号运算符重载
    //p2会无效
    v.push_back(p2);
#ifndef MAUTO_PTR_H
#define MAUTO_PTR_H

template<typename T>
class Mauto_ptr
{
private:
    T* _ptr;
public:
    //explicit防止隐式构造
    explicit Mauto_ptr(T* ptr = NULL)//构造函数
    {
        _ptr = ptr;
    }

    Mauto_ptr(Mauto_ptr& src)//拷贝构造
    {
        _ptr = src._ptr;
        src._ptr = NULL;
    }

    Mauto_ptr<T>& operator=(Mauto_ptr& src)//等号运算符重载
    {
        if (this == &src)
        {
            return *this;
        }

        if (NULL != _ptr)
        {
            delete _ptr;
        }

        _ptr = src._ptr;
        src._ptr = NULL;
    }

    T& operator*()//解引用运算符
    {
        return *_ptr;
    }

    T* operator->()
    {
        return _ptr;
    }

    T* get()
    {
        return _ptr;
    }

    T* release()
    {
        T* tmp = _ptr;
        _ptr = NULL;
        return tmp;
    }

    void reset(T* ptr = NULL)//把自己重新换个值
    {
        if (NULL != _ptr)
        {
            delete _ptr;
        }
        _ptr = ptr;
    }


    ~Mauto_ptr()
    {
        if (NULL != _ptr)
        {
            delete _ptr;
        }
        _ptr = NULL;
    }
};

unique_ptr(唯一的指针)

允许隐式构造
不允许拷贝构造
不允许等号运算符

不能让多个智能指针指向同一块空间

和auto_ptr 比较
允许隐式构造
不允许拷贝构造
不允许等号运算符
可以加入数组指针
存在move函数进行指针转移

进行指针delete的时候调用删除器

    int* p1 = new int(10);
    unique_ptr<int> p2(p1);
    cout << *p2 << endl;
    //p2.reset(p1);
    cout << *p2 << endl;
    //unique_ptr<int> p3(p1);
    //unique_ptr<int> p3 = p2;//不允许拷贝构造
    unique_ptr<int> p4;
    //p4 = p2;//不允许等号运算符重载

    //int* arr = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
    //unique_ptr<int[]> parr(arr);
    //cout << parr[2] << endl;

    //operator  bool
    /*
    if (parr)
    {

    }*/

    //parr.swap()

    //和release完成的功能一致
    p4 = move(p2);//把p2干掉转移到p4

    //p4 = new int(10);
    cout << *p4 << endl;

    unique_ptr<int> p6 = fun(p4);
    cout << *p6 << endl;

    vector<unique_ptr<int>> v;//直接引用
    //v.push_back()
    vector<auto_ptr<int>> v1;
    auto_ptr<int> p7(new int(100));
    v1.push_back(auto_ptr<int>(new int(100)));
    cout << *(v1[0]) << endl;
    //cout << *p7 << endl;

 

#ifndef MUNIQUE_PTR
#define MUNIQUE_PTR

template<typename T>
class Munique_ptr
{
private:
    T* _ptr;
public:
    //explicit防止隐式构造
    Munique_ptr(T* ptr = NULL)
    {
        _ptr = ptr;
    }

    //delete的成员方法不允许再生成
    Munique_ptr(Munique_ptr& src) = delete;

    Munique_ptr<T>& operator=(Munique_ptr& src) = delete;

    //&& 右值引用  ---   引用一个马上释放的对象
    Munique_ptr(Munique_ptr&& src)
    {
        _ptr = src._ptr;
    }

    Munique_ptr<T>& operator=(Munique_ptr&& src)
    {
        _ptr = src._ptr;
    }

    T& operator*()
    {
        return *_ptr;
    }

    T* operator->()
    {
        return _ptr;
    }

    T& operator[](int pos)
    {
        return _ptr[pos];
    }

    //bool运算符的重载
    bool operator bool()
    {
        return _ptr;
    }

    void swap(Munique_ptr<T>& src)
    {
        T* tmp = _ptr;
        _ptr = src._ptr;
        src._ptr = tmp;
    }

    T* get()
    {
        return _ptr;
    }

    T* release()
    {
        T* tmp = _ptr;
        _ptr = NULL;
        return tmp;
    }

    void reset(T* ptr = NULL)
    {
        if (NULL != _ptr)
        {
            delete _ptr;
        }
        _ptr = ptr;
    }

    ~Munique_ptr()
    {
        if (NULL != _ptr)
        {
            delete _ptr;
        }
        _ptr = NULL;
    }
};


template<typename T>
Munique_ptr<T>&& mmove(Munique_ptr<T>& src)//允许传引用,不允许传参
{
    return src.release()
}

shared_ptr(强智能指针)

有引用计数

交叉引用会引起无法释放

 

有引用计数

#include"mshared_ptr.h"
#include"mweak_ptr.h"
template<typename T>
map<T*, int>* Mshared_ptr<T>::_map = new map<T*, int>;

template<typename T>
mutex Mshared_ptr<T>::_mu;

class Pb;

class Pa
{
public:
    Pa(Pb* pb = NULL)
    {}

    Mweak_ptr<Pb> _pb;
};

class Pb
{
public:
    Pb(Pa* pa = NULL)
    {}

    Mweak_ptr<Pa> _pa;
};



int main()
{
    /*
    shared_ptr

    有引用计数

    交叉引用会引起无法释放

    */
#if 0
    int* p1 = new int(100);
    Mshared_ptr<int> p2(p1);
    Mshared_ptr<int> p3 = p2;
    Mshared_ptr<int> p4;
    p4 = p3;
    cout << p2.use_count() << endl;//use_count:返回计数器
    Mshared_ptr<int>* p5 = new Mshared_ptr<int>(p1);
    cout << p2.use_count() << endl;
    delete p5;
    cout << p2.use_count() << endl;

#endif 

    Mshared_ptr<Pa> spa = new Pa();
    Mshared_ptr<Pb> spb = new Pb();
    cout << spa.use_count() << endl;
    cout << spb.use_count() << endl;
#ifndef MSHAERD_PTR_H
#define MSHAERD_PTR_H
#include<iostream>
#include<map>
#include<iterator>
#include<mutex>
using namespace std;

template<typename T>
class Mshared_ptr
{
private:
    T* _ptr;
    static map<T*, int>* _map;
    static mutex _mu;

public:
    Mshared_ptr(T* ptr = NULL)
    {
        cout << "Mshared_ptr(T* ptr = NULL)" << endl;
        _ptr = ptr;
        typename map<T*, int>::iterator it = _map->find(ptr);
        if (it != _map->end())
        {
            _mu.lock();
            it->second++;//计数器++操作
            _mu.unlock();
        }
        else
        {
            _mu.lock();
            _map->insert(make_pair(_ptr, 1));
            _mu.unlock();
        }
    }

    Mshared_ptr(const Mshared_ptr<T>& src)
    {
        cout << "Mshared_ptr(Mshared_ptr<T>& src)" << endl;
        _ptr = src._ptr;
        _mu.lock();
        (*_map)[_ptr]++;
        _mu.unlock();
    }

    Mshared_ptr<T> operator=(const Mshared_ptr<T>& src)
    {
        cout << "Mshared_ptr<T> operator=(Mshared_ptr<T>& src);" << endl;
        if (_ptr == src._ptr)
        {
            return *this;
        }

        _mu.lock();
        if (0 == --(*_map)[_ptr])//引用计数为空
        {
            if (NULL != _ptr)
            {
                delete _ptr;
            }
        }

        _ptr = src._ptr;
        (*_map)[_ptr]++;
        _mu.unlock();

        return*this;
    }

    ~Mshared_ptr()
    {
        cout << "~Mshared_ptr()" << endl;
        _mu.lock();
        if (0 == --(*_map)[_ptr])
        {
            if (NULL != _ptr)
            {
                cout << "delete" << endl;
                delete _ptr;
            }
        }
        _mu.unlock();
        _ptr = NULL;
    }

    T& operator*()//解引用
    {
        return *_ptr;
    }
    T* operator->()
    {
        return _ptr;
    }
    T& operator[](int pos)
    {
        return _ptr[pos];
    }

    /*
    T* operator bool()
    {
        return _ptr;
    }*/
    T* get()
    {
        return _ptr;
    }
    int use_count()
    {
        return (*_map)[_ptr];
    }

};

 

交叉引用会引起无法释放

    Mshared_ptr<Pa> spa = new Pa();
    Mshared_ptr<Pb> spb = new Pb();
    cout << spa.use_count() << endl;
    cout << spb.use_count() << endl;

weak_ptr(弱智能指针)

不能直接使用

防止交叉引用

如果weak_ptr转换为shared_ptr,如果指向的内存已
释放,就会转换失败

多线程时候用来进行不确定生存周期的指针的
多线程传递

#include"mshared_ptr.h"
#include"mweak_ptr.h"
template<typename T>
map<T*, int>* Mshared_ptr<T>::_map = new map<T*, int>;

template<typename T>
mutex Mshared_ptr<T>::_mu;

class Pb;

class Pa
{
public:
    Pa(Pb* pb = NULL)
    {}

    Mweak_ptr<Pb> _pb;
};

class Pb
{
public:
    Pb(Pa* pa = NULL)
    {}

    Mweak_ptr<Pa> _pa;
};
Mshared_ptr<Pa> spa = new Pa();
    Mshared_ptr<Pb> spb = new Pb();
    cout << spa.use_count() << endl;
    cout << spb.use_count() << endl;

    spa->_pb = spb.get();
    spb->_pa = spa.get();
    cout << spa.use_count() << endl;
    cout << spb.use_count() << endl;

    //Mweak_ptr<int> wp1 = new int(10);//weak:不能直接引用   错误
//不占引用计数,析构的时候也不用delete
//cout << *wp1 << endl; //Mshared_ptr<int> sp1 = wp1.lock();//转换shared_ptr,才可以使用
//若要用,让wp1lock一下,返回一个强制指针
//cout << *sp1 << endl;
#ifndef MWEAK_PTR_H
#define MWEAK_PTR_H
#include"mshared_ptr.h"

template<typename T>
class Mweak_ptr
{
private:
    T* _ptr;
public:
    Mweak_ptr(T* ptr = NULL)
    {
        _ptr = ptr;
    }
    Mweak_ptr(Mweak_ptr<T>& src)
    {
        _ptr = src._ptr;
    }
    Mweak_ptr<T>& operator=(Mweak_ptr<T>& src)
    {
        _ptr = src._ptr;
        return *this;
    }
    T* operator=(T* ptr)
    {
        _ptr = ptr;
        return ptr;
    }

    ~Mweak_ptr() {}

    Mshared_ptr<T> lock()
    {
        return Mshared_ptr<T>(_ptr);
    }
};