Handle类与智能指针

作者: eesly_yuan | 来源:发表于2014-09-18 01:23 被阅读330次

Handle类与智能指针的用途或者说是设计它的目的是,能够让我不必去复制对象,同时能够达到运行时绑定对象的方法

今天在前面看到了智能指针的定义及用途,后面又看到了handle类,很好奇,这二者有什么区别,于是各种google,大致得出下面的结论(仅供参考)
智能指针主要目的在于使用RAII管理资源,实现资源的自动释放。
句柄类也实现了智能指针的功能,但是其主要目的是为了在数组中实现多态。

handle类行为类似指针,复制handle对象不会复制其基础对象,复制之后,两个handle指向同一个基础对象。创建一个handle对象,用户需要传递属于有handle管理类型的动态分配对象的地址,从此刻起,handle将拥有这个对象,并且一旦不在有handle对象与该对象关联,handle类负责删除该对象。这个与指针很像,可以说二者基本一致,只是在用的领域有一些不同。

智能指针或者说Handle有三种写法

  • 1、写一个类specialClass,这个类包含需要管理成员指针和引用计数,然后定义一个handle类其中只有一个成员specialClass*管理我们刚刚那个类如下所示
 //all member is private..only assess by Handle
 class UPoint
 {
   friend class Handle;
   
   Point p;
   int u;//count
 
   UPoint():u(0){}
   UPoint(const Point&pv):p(pv){}
   UPoint(int x,int y):p(x,y),u(1){}
   UPoint(const UPoint &up):p(up.p),u(1){}
 };
//handle类管理
class Handle
{
public:
    Handle():up(new UPoint){}
    Handle(int x,int y):up(new UPoint(x,y)){}
    Handle(const Point&p):up(new UPoint(p)){}
    Handle(const Handle &h);
    ~Handle();
    Handle& operator=(const Handle &h);
    int x() const{ return up->p.x(); }
    int y() const{ return up->p.y(); }
    Handle& x(int);
    Handle& y(int);
private:
    UPoint *up;
    void allocup();
};
  • 2、可以看到第一种方法,计数是由UPoint来实现的,由Handle来管理。但做为编写者的我们肯定是不愿意这么写的.这意味着每写一个Handle都得写一个这样的Uxxxx.实在是费事。因此,我们可以很直观的想到一个写法,即在Handle里面指向的是Point *p和int *count;,有一个类似的例子如下
#ifndef MYHANDLE
#define MYHANDLE
template<typename T>
class Handle
{
public:
    //默认构造函数
    Handle(T *p = 0):ptr(p),use(new size_t(1)){}
    //复制构造函数
    Handle(const Handle & rhs):ptr(rhs.ptr),use(rhs.use){(*use)++;}
    //赋值函数
    Handle & operator=(const Handle & rhs)
    {
        *(rhs.use)++;
        removeRef();
        ptr = rhs.ptr;
        use = rhs.use;
        return *this;
    }
    //析构函数
    ~Handle(){removeRef();}
    //指针解引用和箭头操作符,两个版本
    T& operator*();
    T* operator->();
    const T& operator*() const;
    const T* operator->() const;
private:
    T * ptr;
    size_t * use;
    void removeRef()
    {
        if (--(*use) == 0)
        {
            delete ptr;
            delete use;
        }
    }
};
  • 3、上述这种方法是一个很好的解决方式,但还有一种方式是定义一个引用计数类,专门用于管理引用计数,让handle管理指针的行为,如下例子
#ifndef MYUC
#define MYUC
class UseCount
{
public:
    //默认构造函数
    UseCount():count(new size_t(1)){}
    //复制构造函数
    UseCount(const UseCount& uc):count(uc.count){ ++*count;}
    //赋值操作符
    UseCount& operator=(const UseCount &u){
        reattach(u);
        return *this;
    }
    //析构函数
    ~UseCount(){ 
        if (--*count == 0)
            delete count;
    }
    bool isonly() { return *count == 1;}//判断是否只指向一个计数,用于判断是否要删除
    bool reattach(const UseCount &u);//重新连接,用于复制
    bool makeonly();//分配一个新的,用于写时复制技术
private:
    size_t *count;//计数
};
//用于定义赋值操作的时候使用
bool UseCount::reattach(const UseCount &u)
{
    ++*u.count;
    if (-- *count == 0)
    {
        delete count;
        count = u.count;
        return true;     
    }
    count = u.count;
    return false; 
}
bool UseCount::makeonly()//用于写时复制
{
    if (*count == 1)
        return false;
    --*count;
    count = new size_t(1);
    return true;
}
//handle 管理类
template<typename T>
class HandleC
{
public:
    //默认构造函数
    HandleC(T *q = 0):p(q){};
    //复制构造函数
    HandleC(const HandleC &h):p(h.p),count(h.count){};//复制构造函数也很简单.其实可以省略,也不会出错
    //赋值操作符
    HandleC& operator=(const HandleC &rhs);
    //析构函数,先析构这个析构函数内的内容,在析构类的成员
    ~HandleC(){if(count.isonly()) delete p;}

    //解引用和->操作符
    T * operator->();
    T & operator*();
private:
    T *p;//被Handle的对象
    UseCount count;//使用UseCount
};
template<typename T> HandleC<T>& HandleC<T>::operator =(const HandleC<T> &rhs)
{
    if (count.reattch(rhs.count))
        delete p;
    p = rhs.p;
    return *this;
}
template<typename T> T*HandleC<T>::operator->()
{
    if (p) return p;
    throw std::runtime_error("access through unbound Handle");
}
template<typename T> T&HandleC<T>::operator*()
{
    if (p) return *p;
    throw std::runtime_error("dereference of unbound Handle");
}
#endif   

相关文章

  • Handle类与智能指针

    Handle类与智能指针的用途或者说是设计它的目的是,能够让我不必去复制对象,同时能够达到运行时绑定对象的方法 今...

  • C++智能指针

    引用计数技术及智能指针的简单实现 基础对象类 辅助类 智能指针类 使用测试 参考: C++ 引用计数技术及智能指针...

  • 第十六章 string类和标准模板库(2)智能指针模板类

    (二)智能指针模板类 智能指针是行为类似指针的类对象,但这种对象还有其他便于管理内存的功能。 1.使用智能指针 (...

  • C++ 引用计数技术及智能指针的简单实现

    1.智能指针是什么 简单来说,智能指针是一个类,它对普通指针进行封装,使智能指针类对象具有普通指针类型一样的操作。...

  • 智能指针原理,并实现一个简单的智能指针。

    智能指针:实际指行为类似于指针的类对象,它的一种通用实现方法是采用引用计数的方法。 1.智能指针将一个计数器与类指...

  • 智能指针

    原理: 智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针。智能指针的类都是栈上的对象...

  • C++智能指针

    智能指针其实本质是一个模板类,一般使用是用的这个类的对象,而不是指针智能指针体现在内存释放问题,用智能指针管理ne...

  • 智能指针

    1. 什么是智能指针? 智能指针是行为类似于指针的类对象,但这种对象还有其他功能。 2. 为什么设计智能指针? 引...

  • Rust for cpp devs - 智能指针

    与 cpp 类似,Rust 也有智能指针。Rust 中的智能指针与引用最大的不同是,智能指针 own 内存,而引用...

  • Android基础--智能指针

    智能指针分为3类为轻量级指针(Light Pointer)、强指针(Strong Pointer)和弱指针(Wea...

网友评论

    本文标题:Handle类与智能指针

    本文链接:https://www.haomeiwen.com/subject/jmhutttx.html