C++:线上课程2_15(智能指针auto_ptr)

RAII与智能指针
auto_ptr的弃用原因
unique_ptr的使用
shared_ptr的使用&线程安全
weak_ptr的作用


智能指针

1.什么是RAII?

RAll (Resource Acquisition ls lnitialization)是由c++之父Bjarne Stroustrup提出的,中文翻译为资源获取即初始化,使用局部对象来管理资源的技术称为资源获取即初始化;这里的资源主要是指操作系统中有限的东西如内存(heap),网络套接字,互斥量,文件句柄等等,局部对象是指存储在栈的对象,它的生命周期是由操作系统来管理的无需人工介入。

2.RAII的原理

资源的使用一般经历三个步骤:
a.获取资源(创建对象)(操作系统内核资源:线程,进程,文件等等)
b.使用资源
c.销毁资源(析构对象)

3.裸指针

不能判断指针指向一个对象还是一组对象,所以销毁不能进行

int main()
{
    //裸指针
    int* ip = NULL;
    Object* op = NULL;
}

3.1裸指针存在问题

  1. 难以区分指向的是单个对象还是一个数组;

  2. 使用完指针之后无法判断是否应该销毁指针,因为无法判断指针是否“拥有”指向的对象;

  3. 在已经确定需要销毁指针的情况下,也无法确定是用delete关键字删除,还是有其他特殊的销毁机制,例如通过将指针传入某个特定的销毁函数来销毁指针;

  4. 即便已经确定了销毁指针的方法,由于1的原因,仍然无法确定到底是用delete(销毁单个对象)还是 delete[ ] (销毁一个数组);

  5. 假设上述的问题都解决了,也很难保证在代码的所有路径中(分支结构,异常导致的跳转),有且仅有一次销毁指针操作;任何一条路径遗漏都可能导致内存泄露,而销毁多次则会导致未定义行为;

  6. 理论上没有方法来分辨一个指针是否处于悬挂状态;

4.智能指针(my_auto_ptr弃用)

4.1示例1

#include<iostream>
#include<list>
#include<vector>
#include<queue>
#include<stack>
#include<stdio.h>
using namespace std;

class Object
{
public:
    int value;
public:
    Object(int x = 0) :value(x)
    {
        cout << "Create Object : " << this << endl;
    }
    ~Object()
    {
        cout << "Destroy Object : " << this << endl;
    }
};
template<class _Ty>
class my_auto_ptr
{
private:
    bool _Owns;
    _Ty* _Ptr;
public:
    my_auto_ptr(_Ty* p = NULL) :_Owns(p != NULL), _Ptr(p) {}
    ~my_auto_ptr()
    {
        if (_Owns)
        {
            delete _Ptr;
        }
        _Ptr = NULL;
    }
};
void fun()
{
    my_auto_ptr<Object> obj(new Object(10));
}
int main()
{
    fun();
}

运行结果
在这里插入图片描述

4.2示例2

#include<iostream>
#include<list>
#include<vector>
#include<queue>
#include<stack>
#include<stdio.h>
using namespace std;

class Object
{
public:
    int value;
public:
    Object(int x = 0) :value(x)
    {
        cout << "Create Object : " << this << endl;
    }
    ~Object()
    {
        cout << "Destroy Object : " << this << endl;
    }
    int& Value()
    {
        return value;
    }
    const int& Value() const
    {
        return value;
    }
};
template<class _Ty>
class my_auto_ptr
{
private:
    bool _Owns;
    _Ty* _Ptr;
public:
    my_auto_ptr(_Ty* p = NULL) :_Owns(p != NULL), _Ptr(p) {}
    ~my_auto_ptr()
    {
        if (_Owns)
        {
            delete _Ptr;
        }
        _Ptr = NULL;
    }
    _Ty* get() const
    {
        return _Ptr;
    }
    _Ty& operator*() const
    {
        return *(get());
    }
    _Ty* operator->() const
    {
        return get();
    }
};

void fun()
{
    my_auto_ptr<Object> obj(new Object(10));

    cout << obj->Value() << endl;//重载指向符
    cout << (*obj).Value() << endl;//重载解引用
}
int main()
{
    fun();
}

运行结果
在这里插入图片描述

4.3示例3

    my_auto_ptr(const my_auto_ptr& op) :_Owns(op._Owns)
    {
        if (Owns)
        {
            _Ptr = op._Ptr;
        }
    }
    int main()
{
    my_auto_ptr<Object> pobja(new Object(19));
    my_auto_ptr<Object> pobjb(pobja);//
}
//pobja和pobjb两个对象共同拥有同一个资源

4.4完整代码

my_auto_ptr 所有代码

#include<iostream>
#include<list>
#include<vector>
#include<queue>
#include<stack>
#include<stdio.h>
using namespace std;

class Object
{
public:
    int value;
public:
    Object(int x = 0) :value(x)
    {
        cout << "Create Object : " << this << endl;
    }
    ~Object()
    {
        cout << "Destroy Object : " << this << endl;
    }
    int& Value()
    {
        return value;
    }
    const int& Value() const
    {
        return value;
    }
};

template<class _Ty>
class my_auto_ptr
{
private:
    bool _Owns;
    _Ty* _Ptr;
public:
    my_auto_ptr(_Ty* p = NULL) :_Owns(p != NULL), _Ptr(p) {}
    ~my_auto_ptr()
    {
        if (_Owns)
        {
            delete _Ptr;
        }
        _Ptr = NULL;
    }
    my_auto_ptr(const my_auto_ptr& op) :_Owns(op._Owns)//拷贝构造函数(转移拥有权)
    {
        if (Owns)
        {
            _Ptr = op._Ptr;
        }
    }
    _Ty* get() const
    {
        return _Ptr;
    }
    _Ty& operator*() const
    {
        return *(get());
    }
    _Ty* operator->() const
    {
        return get();
    }
    void reset(_Ty* p = NULL)//重置函数
    {
        if (_Owns)
        {
            delete _Ptr;
        }
        _Ptr = NULL;
    }
    _Ty* release()//释放函数
    {
        _Ty* tmp = NULL;
        if (_Owns)
        {
            ((my_auto_ptr*)this)->_Owns = false;
            tmp = _Ptr;
            ((my_auto_ptr*)this)->_Ptr = NULL;
        }
        return tmp;
    }
};
void fun(my_auto_ptr<Object> apx)
{
    int x = apx->Value();
    cout << x << endl;
}
int main()
{
    my_auto_ptr<Object> pobja(new Object(19));
    fun(pobja);
    int a = pobja->Value();
    my_auto_ptr<Object> pobjb(pobja);
}

5.智能指针(拥有独有对象所有权语义的智能指针)

5.1unique_ptr指针特点

不允许赋值,不允许用一个对象初始化另一个对象,不允许

void fun(std::unique_ptr<Object> apx)
{
    std::unique_ptr<Object> obj(new Object(10));
    return obj;
}
int main()
{
    std::unique_ptr<Object> pobja(new Object(10));
    std::unique_ptr<Object> pobjb(pobja);//不允许用一个对象初始化另一个对象(原因:底层代码删除了拷贝构造函数)
    std::unique_ptr<Object> pobjb;
    pobjb = pobja;//不允许赋值

    fun(pobja);//编译错误
    pobja = fun();//编译错误,拷贝构造函数无参

    return 0;
}

5.2unique_ptr全部代码

#include<iostream>
#include<list>
#include<vector>
#include<queue>
#include<stack>
#include<stdio.h>
using namespace std;
template<class _Ty>
class my_unique_ptr
{
private:
    int value;
public:
    _Ty* _Ptr;
    my_unique_ptr(const my_unique_ptr&) = delete;
    my_unique_ptr& operator=(const my_unique_ptr&) = delete;

public:
    typedef _Ty* pointer;
    typedef _Ty element_type;
public:
    my_unique_ptr(_Ty* p = NULL) :_Ptr(p) {}
    ~my_unique_ptr()
    {
        delete _Ptr;
    }
    my_unique_ptr(my_unique_ptr&& _Y)
    {
        _Ptr = _Y._Ptr;
        _Y._Ptr = NULL;
    }
    my_unique_ptr& operator=(my_unique_ptr&& _Y)
    {
        if (this == &_Y)
        {
            return *this;
        }
        delete _Ptr;
        _Ptr = _Y._Ptr;
        _Y._Ptr = NULL;
        return *this;
    }
};
class Object
{
public:
    int value;
public:
    Object(int x = 0) :value(x)
    {
        cout << "Create Object : " << this << endl;
    }
    ~Object()
    {
        cout << "Destroy Object : " << this << endl;
    }
    int& Value()
    {
        return value;
    }
    const int& Value() const
    {
        return value;
    }
};
std::unique_ptr<Object> fun()
{
    std::unique_ptr<Object> obj(new Object(10));
    return obj;
}

int main()
{
    std::unique_ptr<Object> pobja(new Object(100));
    std::unique_ptr<Object> pobjb(std::move(pobja));

    pobja = (std::unique_ptr<Object>&&)(pobjb);
    pobja = std::move(pobjb);

    return 0;
}

5.3代码示例(unique_ptr代码示例)

using namespace std;

template<class T,class D>//完全泛化
class my_unique_ptr
{
public:
    my_unique_ptr()
    {
        cout << "T,D" << endl;
    }
};

template<class T, class D>//部分特化
class  my_unique_ptr<T*, D*>
{
public:
    my_unique_ptr()
    {
        cout << "const T*,D*" << endl;
    }
};

template<class T, class D>//部分特化
class  my_unique_ptr<const T*, D*>
{
public:
    my_unique_ptr()
    {
        cout << "const T*,D*" << endl;
    }
};

template<>//完全特化
class  my_unique_ptr<const char*, const char*>
{
public:
    my_unique_ptr()
    {
        cout << "const char*,const char*" << endl;
    }
};

template<class T, class D>
class my_unique_ptr<T[], D>
{
public:
    my_unique_ptr()
    {
        cout << "T[],D" << endl;
    }
};

int main()
{
    my_unique_ptr<int, int> a;
    my_unique_ptr<int[], int> b;

    return 0;
}

5.4代码示例(unique_ptr代码示例)

class Object
{
public:
    int value;
public:
    Object(int x = 0) :value(x)
    {
        cout << "Create Object : " << this << endl;
    }
    ~Object()
    {
        cout << "Destroy Object : " << this << endl;
    }
    int& Value()
    {
        return value;
    }
    const int& Value() const
    {
        return value;
    }
};
struct delete_object
{
    void operator()(Object* op)
    {
        if (op == NULL) return;
        delete op;
    }
};
int main()
{
    std::unique_ptr<Object> pobja(new Object(10));
    std::unique_ptr<Object, delete_object> pobjb(new Object(20));

    return 0;
}

运行结果

在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值