两种智能指针-RAII智能指针和引用计数智能指针

原创 2015年11月17日 23:46:16

两种智能指针-RAII智能指针和引用计数智能指针

RAII简介

RAII的全称是:Resource Acquisition Is Initialization 也就是“资源获取就是初始化”。就像内存分配是在变量初始化的时候分配的;比如,当程序结束时,系统会自动释放程序所使用的资源;函数传值时,当函数调用结束,该值也将消亡。

RAII智能指针代码参考

#include <iostream>

#define SAFE_DELETE(ptr) if(nullptr!=ptr){delete ptr;ptr=nullptr;}//安全delete

template<typename T>class SmartPtr{
public:
    typedef T element_type;

    explicit SmartPtr(T * ptr=nullptr):m_ptr(ptr){}

    SmartPtr(SmartPtr<T> & ptr):m_ptr(ptr.release()){}

    inline T * release(){
        T * tmp=m_ptr;
        SAFE_DELETE(m_ptr);
        return m_ptr;
    }

    SmartPtr<T>& operator=(SmartPtr<T>& ptr){
        if(&ptr != this){
            SAFE_DELETE(m_ptr);
            m_ptr=ptr.release();
        }
        return *this;
    }

    SmartPtr<T>& operator= (T * ptr){
        if(ptr!=ptr.get()){
            SAFE_DELETE(m_ptr);
            m_ptr=ptr.release();
        }
        return *this;
    }

    ~SmartPtr(){SAFE_DELETE(m_ptr);}

    inline T * operator->(){return m_ptr;}
    inline T & operator*(){return *m_ptr;}

    inline void reset(T * ptr=nullptr){
        SAFE_DELETE(m_ptr);
        m_ptr=ptr;
    }

    inline T * get()const{return m_ptr;}

private:
    T * m_ptr;
};

int main(){
    SmartPtr<int>ptr(new int(234));
    std::cout<<*ptr<<std::endl;
    std::cout<<*ptr.get()<<std::endl;
    return 0;
}

第二种写法:

#include <iostream>

template<typename T>
inline void SafeDelete(T*& ptr) {
    if (ptr != nullptr) {
        delete ptr;
        ptr = nullptr;
    }
}

template<typename T>
class SmartPtr {
public:
    SmartPtr() :m_ptr(nullptr) {}
    SmartPtr(T * ptr):m_ptr(ptr){}
    SmartPtr(const SmartPtr<T> & other) = delete;
    template<typename Tx>SmartPtr(const SmartPtr<Tx> & other) = delete;
    SmartPtr(SmartPtr<T>&&other){
        T *ptr = other.m_ptr;
        other.m_ptr = m_ptr;
        m_ptr = ptr;
    }
    ~SmartPtr() { SafeDelete(m_ptr); }
    SmartPtr & operator=(const SmartPtr<T>& other) = delete;
    template<typename Tx>SmartPtr & operator=(const SmartPtr<Tx>&other) = delete;
    SmartPtr & operator=(const SmartPtr<T>&&other) {
        if (this != &other) {
            T *ptr = other.m_ptr;
            other.m_ptr = m_ptr;
            m_ptr = ptr;
        }
    }
    inline T & operator*() {
        return *m_ptr;
    }
    inline T * operator->() {
        return m_ptr;
    }
    inline const T & operator*()const {
        return *m_ptr;
    }
    inline const T * operator->()const {
        return m_ptr;
    }
    inline T * release(){
        T * bk = m_ptr;
        m_ptr = nullptr;
        return bk;
    }
    inline void reset(T * ptr = nullptr) {
        SafeDelete(m_ptr);
        m_ptr = ptr;
    }
    inline T * get() { return m_ptr; }
    inline const T * get()const { return m_ptr; }
private:
    T * m_ptr;
};

struct My {
    int data = 100;
};

int main() {
    SmartPtr<int> ptr(new int(2342));
    std::cout << *ptr << std::endl;
    SmartPtr<My> ptrx(new My);
    std::cout << ptrx->data << std::endl;
    std::cin.get();
    return 0;
}

引用计数版本参考代码

引用计数使用到了代理模式的相关知识:参考
http://baike.baidu.com/view/2645890.htm

#include <iostream>
#include <windows.h>

#define SAFE_DELETE(ptr) if(ptr!=nullptr){delete ptr;ptr=nullptr;}

class RefCount{
public:
    RefCount():m_count(0){}
    ~RefCount(){}
    unsigned long AddRef(){return InterlockedIncrement(reinterpret_cast<long *>(&m_count));}
    unsigned long Release(){return InterlockedDecrement(reinterpret_cast<long *>(&m_count));}
    inline void Reset(){m_count=0;}
private:
    unsigned long m_count;
};

template<typename T>class SmartPtr{
public:
    typedef T element_type;

    explicit SmartPtr():m_ptr(nullptr),m_counter(new RefCount){m_counter->AddRef();}

    SmartPtr(T * ptr):m_ptr(ptr),m_counter(new RefCount){m_counter->AddRef();}

    SmartPtr(const SmartPtr<T>& ptr)=delete;

    SmartPtr(SmartPtr<T>&& ptr):m_ptr(ptr.m_ptr),m_counter(ptr.m_counter){
        ptr.m_ptr=nullptr;
        ptr.m_counter=nullptr;
    }

    SmartPtr<T>& operator=(const SmartPtr<T>& ptr)=delete;

    SmartPtr<T>& operator=(SmartPtr<T>&& ptr){
        if(m_counter && m_counter->Release()==0){
            SAFE_DELETE(m_ptr);
            SAFE_DELETE(m_counter);
        }
        m_ptr=ptr.m_ptr;
        ptr.m_ptr=nullptr;
        m_counter=ptr.m_counter;
        ptr.m_counter=nullptr;
        return *this;
    }

    SmartPtr<T>& operator=(T * ptr){
        if(ptr != m_ptr){
            if(m_counter && m_counter->Release()==0){
                SAFE_DELETE(m_ptr);
                m_counter->Reset();
            }
            m_ptr=ptr;
            m_counter->AddRef();
        }
    }

    inline T * get()const{return m_ptr;}

    inline T & operator*(){return *m_ptr;}

    inline T * operator->(){return m_ptr;}

    inline void swap(SmartPtr<T> & ptr){
        T * tmp=ptr.m_ptr;
        RefCount * rtmp=ptr.m_counter;
        ptr.m_ptr=m_ptr;
        ptr.m_counter=m_counter;
        m_ptr=tmp;
        m_counter=rtmp;
    }

    inline T * release(){
        T * tmp=m_ptr;
        m_ptr=nullptr;
        return m_ptr;
    }

private:
    RefCount * m_counter;
    T * m_ptr;
};

int main(){
    SmartPtr<int>ptr(new int(2432));
    std::cout<<*ptr<<std::endl;
    std::cout<<*ptr.get()<<std::endl;
    return 0;
}

关于InterlockedIncrement和InterlockedDecrement参考:
http://baike.baidu.com/view/6235756.htm

版本2:

#include <iostream>
#include <Windows.h>

template<typename T>
inline void SafeDelete(T*& ptr) {
    if (ptr != nullptr) {
        delete ptr;
        ptr = nullptr;
    }
}

class RefCounter {
public:
    RefCounter():m_cnt(0){}
    ~RefCounter() {}
    std::size_t RefAdd() { return InterlockedIncrement(&m_cnt); }
    std::size_t Release() { return InterlockedDecrement(&m_cnt); }
    std::size_t getcnt() { return m_cnt; }
    void reset() { m_cnt = 0; }
private:
    size_t m_cnt;
};

template<typename T>
class SmartPtr {
public:
    SmartPtr() :m_ptr(nullptr) ,m_counter(new RefCounter){
        m_counter->RefAdd();
    }
    SmartPtr(T * ptr) :m_ptr(ptr), m_counter(new RefCounter) {
        m_counter->RefAdd();
    }
    SmartPtr(const SmartPtr<T>& other) = delete;
    template<typename Tx>SmartPtr(const SmartPtr<Tx>&other) = delete;
    SmartPtr(SmartPtr<T>&&other) :m_ptr(other.m_ptr),m_counter(other.m_counter){
        other.m_ptr = nullptr;
        other.m_counter = nullptr;
    }
    ~SmartPtr() {
        if (m_counter != nullptr && m_counter->Release() == 0) {
            SafeDelete(m_ptr);
            SafeDelete(m_counter);
        }
    }
    SmartPtr & operator=(const SmartPtr<T>& other) = delete;
    template<typename Tx>SmartPtr & operator=(const SmartPtr<Tx>& other) = delete;
    SmartPtr & operator=(SmartPtr<T>&&other) {
        if (&other != this) {
            if (m_counter != nullptr && m_counter->Release() == 0) {
                SafeDelete(m_ptr);
                SafeDelete(m_counter);
            }
            m_ptr = other.m_ptr;
            m_counter = new RefCounter;
            m_counter->RefAdd();
        }
    }
    T * relaese() {
        if (m_counter != nullptr && m_counter->Release() == 0) {
            SafeDelete(m_ptr);
            SafeDelete(m_counter);
        }
        m_ptr = nullptr;
        m_counter = nullptr;
    }
    void reset(T * ptr = nullptr) {
        if (m_counter != nullptr && m_counter->Release() == 0) {
            SafeDelete(m_ptr);
            SafeDelete(m_counter);
        }
        m_ptr = ptr;
        m_counter = new RefCounter;
        m_counter->RefAdd();
    }
    T & operator*() { return *m_ptr; }
    const T & operator*()const { return *m_ptr; }
    T*operator->() { return m_ptr; }
    const T*operator->()const { return m_ptr; }
private:
    T * m_ptr;
    RefCounter * m_counter;
};

struct My {
    int data = 1000;
};

int main() {
    SmartPtr<My> ptr(new My);
    std::cout << ptr->data << std::endl;
    SmartPtr<double> ptrx(new double(24.2));
    std::cout << *ptrx << std::endl;
    std::cin.get();
    return 0;
}

注:代码尚有缺点。

转载请注明出处

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

C++实现 带引用计数的智能指针

  • 2012年09月05日 23:07
  • 544KB
  • 下载

带引用计数智能指针

智能指针实现的原理是 1.存储引用计数 2.同时共享引用计数内存地址 (注意shared_ptr是用引用计数的,auto_ptr是无引用计数的)...

智能指针(引用计数版)

#include using namespace std; template class smartPoiter; template class u_ptr { private...

关于智能指针,引用计数的学习与实现

自从用过boost的智能指针:shared_ptr之后,一直对引用计数这种东西很好奇,想知道它是如何实现的,尤其是一个ptr改变了引用计数,如何能够即时的让其他的ptr知道; 曾经想过一些方法,比如...

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

转载这篇文章点击打开链接 C++ 引用计数技术及智能指针的简单实现 阅读目录 1.智能指针是什么2.普通指针存在的问题3.什么是引用计数4.智能指针实现 ...

VTK修炼之道80:VTK开发基础_智能指针与引用计数

1.引用计数 VTK经过多年的开发与维护,已经形成了一套稳定的框架和开发规则。因此,了解这些规则和框架是定制VTK类的基础,这其中用到了大量面向对象的设计模式,例如对象工程模式、观察者/命令模式;...

boost库在工作(11)引用计数的智能指针weak_ptr

由于boost库里的shared_ptr采用引用计数的技术,这个技术天生就存在一个缺陷,就是不能存在循环引用的情况,因为这个缺点,引用计数的技术一直没有用到垃圾回收的算法里。既然存在这方面的问题,作为...

cocos2dx-内存管理剖析(智能指针的局限与引用计数的选择)

一、常用内存管理计数 1、智能指针 cocos的内存管理没有用智能指针,智能指针,c++有相应的类型,代码如下: #include using namespace std; class Obj{...

boost库在工作(9)引用计数的智能指针shared_ptr之二

接着下来,需要演示一下怎么样在多个对象里共享一个对象,而不管每个对象的生命周期,就可以及时地把使用的对象在合适地方删除。下面的例子里先定义两个类,然后每个类都引用共享的对象,接着使用完成后,就会在析构...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:两种智能指针-RAII智能指针和引用计数智能指针
举报原因:
原因补充:

(最多只允许输入30个字)