shared_ptr(下) 删除器

1、shared_ptr中的px出现原因

方便对其数据空间的管理,取值和获取地址将极大的方便我们的操作。

2、解决析构函数

避免内存空间的泄漏。new出来的空间都没有释放掉!

释放拥有权靠的是引用计数。

~shared_count(){ 
    if(pi){  //判断所指父类是否为空
        pi->release(); //释放new出来的对象和外部new出来的空间
    }
}
////////////////////////////////////////////////////////////////////////
public:
    virtual void dispose() = 0; //纯虚函数
    void release(){  //在sp_counted_base中
        if(--use_count_ == 0){ //判断use_count是否为0
            dispose();  //因为虚函数,所以子类中实现
            delete this; //先调用析构函数,在释放this指向的空间
        }    
    }
///////////////////////////////////////////////////////////////////////
public:
    void dispose(){
        delete px_; //释放外部new出来的空间
    }

因为要级联释放空间,所以sp_counted_base的析构函数必须是虚函数,才能先调用子类的析构,最后调用自己的析构函数。

结果如下:

use_count和unique函数的实现比较简单

3、拷贝构造和赋值语句

此时应当相当于浅拷贝,use_count加1即可!模型如下:

此时应在shared_ptr和shared_count进行浅拷贝,并在shared_count中加入方法,

    shared_count(shared_count const &r) : pi(r.pi){
        if(pi){
            pi->add_ref_copy(); //在父类中实现这个方法,只要让++use_count_即可!
        }
    }

赋值语句,关键调用swap函数,的认真思考,画画图就好理解多了(前面已经写过这个了)。

        这个赋值语句写的真的很好,既让use_count_加1,又可以让原先的空间符合情况的释放。

    shared_ptr<T>& operator=(shared_ptr<T> const &r){
        if(this != &r){
            this_type(r).swap(*this);//调用拷贝构造,先创建一个无名临时的对象,
        }                         //因为调用了拷贝构造,所以在shared_count中调用方法,
        return *this;             //会让use_count_加1的。
    }
//////////////////////////////////////////////////////////////////////////////////////
    void swap(shared_ptr<T> &other){
        std::swap(px, other.px); //指针的交换
        pn.swap(other.pn);
    }

3、shared_ptr的模拟部分:

#ifndef _CONFIG_H_
#define _CONFIG_H_

#include<iostream>
using namespace std;

//#define DISPLAY

#endif
////////////////////////////////////////////////////////////////////////////////////////
#ifndef _SHARED_PTR_H_
#define _SHARED_PTR_H_

#include"shared_count.h"

template<class T>
class shared_ptr{
    typedef shared_ptr<T> this_type;
public:
    shared_ptr(T *p = 0) : px(p), pn(p){
#ifdef DISPLAY
        cout<<"Create shared_ptr object!"<<endl;
#endif
    }
    shared_ptr(shared_ptr<T> const &r) : px(r.px), pn(r.pn){}
    shared_ptr<T>& operator=(shared_ptr<T> const &r){
        if(this != &r){
            this_type(r).swap(*this);//调用拷贝构造,先创建一个无名临时的对象
        }
        return *this;
    }
    ~shared_ptr(){
#ifdef DISPLAY
        cout<<"Free shared_ptr object"<<endl;
#endif
    }
public:
    T& operator*()const{
        return *(get());
    }
    T* operator->()const{
        return get();
    }
    T* get()const{
        return px;
    }
public:
    long use_count()const{
        return pn.use_count();
    }
    bool unique()const{
        return pn.unique();
    }
    void reset(T *p){
        this_type(p).swap(*this);
    }
    void swap(shared_ptr<T> &other){
        std::swap(px, other.px); //指针的交换
        pn.swap(other.pn);
    }
private:
    T *px;
    shared_count pn;
};

#endif
////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _SHARED_COUNT_H_
#define _SHARED_COUNT_H_

#include"config.h"
#include"sp_counted_base.h"
#include"sp_counted_impl_xx.h"

class shared_count{
public:
    template<class T>  //此时类型不定,写模板函数
        shared_count(T *p) : pi(new sp_counted_impl_xx<T>(p)){
#ifdef DISPLAY
        cout<<"Create shared_cout object!"<<endl;
#endif
    }
    shared_count(shared_count const &r) : pi(r.pi){
        if(pi){
            pi->add_ref_copy();
        }
    }
    ~shared_count(){
#ifdef DISPLAY
        cout<<"Free shared_count object"<<endl;
#endif
        if(pi){
            pi->release();
        }
    }
public:
    long use_count()const{
        return pi != 0 ? pi->use_count() : 0;
    }
    bool unique()const{
        return use_count() == 1;
    }
    void swap(shared_count &r){
        sp_counted_base *tmp = r.pi;
        r.pi = pi;
        pi = tmp;
    }
private:
    sp_counted_base *pi;
};

#endif
//////////////////////////////////////////////////////////////////////////////
#ifndef SP_COUNTED_BASE_H_
#define SP_COUNTED_BASE_H_

#include"config.h"

class sp_counted_base{  //抽象类
public:
    sp_counted_base() : use_count_(1){
#ifdef DISPLAY
        cout<<"Create sp_counted_base object"<<endl;
#endif
    }
    virtual ~sp_counted_base(){
#ifdef DISPLAY
        cout<<"Free sp_counted_base object"<<endl;
#endif
    }
public:
    virtual void dispose() = 0; //纯虚函数
    void release(){
        if(--use_count_ == 0){
            dispose();
            delete this;
        }    
    }
public:
    long use_count()const{
        return use_count_;
    }
    void add_ref_copy(){
        ++use_count_;
    }
private:
    long use_count_;
};

#endif
/////////////////////////////////////////////////////////////////////////////////////
#ifndef SP_COUNTED_IMPL_XX_H_
#define SP_COUNTED_IMPL_XX_H_

#include"sp_counted_base.h"

template<class T>
class sp_counted_impl_xx : public sp_counted_base{
public:
    sp_counted_impl_xx(T *p) : px_(p){
#ifdef DISPLAY
        cout<<"Create sp_counted_impl_xx object"<<endl;
#endif
    }
    ~sp_counted_impl_xx(){
#ifdef DISPLAY
        cout<<"Free sp_counted_impl_xx object"<<endl;
#endif
    }
public:
    void dispose(){
        delete px_;
    }
private:
    T *px_;
};

#endif
////////////////////////////////////////////////////////////////////////////////////
#include<iostream>
#include"shared_ptr.h"
using namespace std;

int main(void){
    int *p = new int(10);
    shared_ptr<int> ps(p);

    cout<<ps.use_count()<<endl;
    cout<<ps.unique()<<endl;

    shared_ptr<int> ps1 = ps;
    cout<<ps.use_count()<<endl;
    cout<<ps.unique()<<endl;
    shared_ptr<int> ps2;
    ps2 = ps;
    cout<<ps.use_count()<<endl;
    cout<<ps.unique()<<endl;

    //cout<<*ps<<endl;
    
}

以上就是对shared_ptr的部分源码剖析的理解了。

4、删除器

删除器d可以是一个函数对象(是一个对象,但是使用起来像函数),也可以是一个函数指针;

可以根据自己定义的方式去管理(释放)内存空间。

有2个特性:函数对象 operator()进行了重载

删除器的使用,调用系统的:

#include<iostream>
#include<boost/smart_ptr.hpp>
using namespace std;
using namespace boost;

void My_Deleter(int *p){ //删除器
    cout<<"HaHa:"<<endl;
    delete p;
}
//靠删除器来管理空间,而不再向之前的调用析构函数。
int main(void){
    int *p = new int(10); //假设p是特殊的资源
    shared_ptr<int> ps(p, My_Deleter);
}

回过头来,对自己的空间进行释放,定义自定义的删除器。不采用默认方式释放,而是

采用自己的方式释放!

删除器自己模拟部分代码:

public:
    template<class Y, class D>
        shared_ptr(Y *p, D d) : px(p), pn(p, d){}//支持传递删除器
/////////////////////////////////////////////////////////////////////////////
    template<class Y, class D>
    shared_count(Y *p, D d) : pi(0){
        typedef Y* P;
        pi = new sp_counted_impl_pd<P, D>(p, d);
    }
///////////////////////////////////////////////////////////////////////////
template<class P, class D>
class sp_counted_impl_pd : public sp_counted_base{
public:
    sp_counted_impl_pd(P p, D d) : ptr(p), del(d){}
public:
    void dispose(){
        delete ptr;
    }
private:
    P ptr;
    D del;
};
//////////////////////////////////////////////////////////////////////////
#include<iostream>
#include"shared_ptr.h"
using namespace std;

void My_Deleter(int *p){ //删除器
    cout<<"HaHa:"<<endl;
    delete p;
}

int main(void){
    int *p = new int(10); 
    shared_ptr<int> ps(p, My_Deleter);
}

以上就是删除器实现的主要代码,是在shared_ptr中实现的。

时间: 2024-12-16 06:23:10

shared_ptr(下) 删除器的相关文章

【C++】智能指针shared_ptr 定位删除器(仿函数)

智能指针shared_ptr 用引用计数实现看起来不错,但却存在问题. 1.引用计数更新存在着线程安全: 2.循环引用--使用一个弱引用智能指针(weak_ptr)来打破循环引用(weak_ptr不增加引用计数) 3.定置删除器和空间分配器 比如打开一个文件的关闭,用malloc开辟出来的空间,用引用计数实现会出现问题. 对改变引用计数时加锁可以解决引用计数更新存在着线程安全. 循环引用问题 #include<iostream> using namespace std; #include<

智能指针的模拟实现shared_ptr 循环引用 定置删除器

auto_ptr与scoped_ptr的实现见本人的上篇博客. 三.shared_ptr shared_ptr的实现原理是通过引用计数来实现,只有当引用计数为1时才释放空间,否则只需将引用计数减1.拷贝和赋值将引用计数加1,具体代码如下: template <typename T> class SharedPtr { public: SharedPtr(); SharedPtr(T* ptr); SharedPtr(const SharedPtr<T>& ap); ~Sha

shared_ptr循环引用&定置删除器

shared_ptr虽然方便,但是它有着一个致命的缺陷就是循环引用问题,因为shared_ptr本身并没有能力解决这个问题,所以我们又引入了弱指针weak_ptr来辅助shared_ptr解决这个问题. 那么循环引用又是什么场景? 举个栗子: 假设现在我们要创建一个双向整形链表,但是这个链表的指针域全部都用shared_ptr维护: struct Node { int _data; shared_ptr<Node> _next; shared_ptr<Node> _prev; }

boost::shared_ptr与定制删除器

shared_ptr shared_ptr是一种智能指针,他的作用如同指针,但会记录有多少shared_ptr指向同一个对象.使用时必须引用头文件<boost/shared_ptr.hpp> template<class T> class ShartedPtr { public: //构造函数 ShartedPtr(T* ptr) :_ptr(ptr) , _pCount(new int(1)) { } //拷贝构造 ShartedPtr(const ShartedPtr<T

Windows 7系统下删除开机引导项的方法

Windows 7系统下删除开机引导项的方法: 1.使用管理员权限运行cmd,在命令行窗口使用  bcdedit 回车 2.查找description为你想删除的段,看对应的标识符是多少, 然后使用 bcdedit  /f  /delete 标识符 示例: bcdedit  /f  /delete {fa817679-23c9-11e1-bcbd-a9093a3d5fb5} 3. win7系统有一个启动管理器 bootmgr 它有一个状态displaybootmenu 默认是no 如果做过多系统

实战c++中的智能指针unique_ptr系列-- unique_ptr的get_deleter方法(自定义删除器)

unique_ptr的成员函数在上一篇博客中几乎全部涵盖,其实还有一个很有踢掉,即std::unique_ptr::get_deleter 字面已经很明显了,就获得deleter: Returns the stored deleter The stored deleter is a callable object. A functional call to this object with a single argument of member type pointer is expected

Windows下删除不需要的服务

开始"--"运行"--"msconfig"回车 在"服务"里面可以找到 至于删除服务项,就请打开注册表("开始"--"运行"--"regedit")然后依次打开HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services,将你所希望删除的服务项从注册表里删除就行了, 建议使用辅助软件来管理你的注册表项目(比如 360 安全卫士以及你说的 Wi

Linux下删除乱码文件

Linux下删除乱码文件: 1. ls -i 列出文件的节点ID, 如: 123456789 2. find ./ -inum 123456789 -print -exec rm -rf {} \; 批量删除: for n in 123456789 987654321;do find . -inum $n -exec rm -f {} \;;done

【智能指针的延伸】两种定制删除器的实现方法

所谓定制删除器,就是向目标模板提供一个可以自由选择析构的接口,这样做的好处就是可以使智能指针模板不再只能单独管理内存,我们还可以用它管理文件指针之类的东西.其实现方法有两种,这里我们以share指针为例.   1.传递一个类的模板参数并给出缺省值,模板中将该类设定为成员变量,通过该类(删除类)的实例化,调用类中所存的删除方法进行删除. 代码如下: #include<iostream> template <class T> struct Del { void operator ()(