两种智能指针-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++的RAII和智能指针小结

RAII:资源分配即初始化,利用构造函数和析构函数定义一个类来完成对资源的分配和释放智能指针主要用来防止内存泄漏,我们来举个栗子,看看为什么会有智能指针这个东东例1:650) this.width=6...
  • qq_29695087
  • qq_29695087
  • 2016年05月31日 09:07
  • 643

【C++】智能指针之引用计数的实现

本文将简单的介绍,C++11中的智能指针的引用计数大致是如何实现的。部分内容节选自 C++ primer 5th。...
  • zone_programming
  • zone_programming
  • 2015年09月11日 15:16
  • 2899

c++11-智能指针和引用计数

一、本节内容 本节内容包括: 对标准库的扩充: 智能指针和引用计数 RAII 与引用计数std::shared_ptrstd::unique_ptrstd::weak_ptr ...
  • icandoit2010
  • icandoit2010
  • 2017年02月23日 10:20
  • 347

智能指针的死穴 -- 循环引用

C++最新标准C++11中已将基于引用计数的智能指针share_prt收入囊中,智能指针的使用门槛越来越低,不需要使用boost库,我们也能轻松享受智能指针给我们带来的方便。 智能指针,正如它的名字...
  • jfkidear
  • jfkidear
  • 2013年06月05日 21:59
  • 5871

C++中的解引用与智能指针

一、概述在C语言和C++中,不管我们用C语言的库函数malloc开辟了一块内存,还是用C++的操作符new出了一块内存,我们都要同过free和delete去释放内存。而对于其他高级语言来说,当我们开辟...
  • jiang_xinxing
  • jiang_xinxing
  • 2017年03月08日 17:22
  • 334

非常经典的C++ 引用计数技术及智能指针的简单实现

阅读目录 1.智能指针是什么2.普通指针存在的问题3.什么是引用计数4.智能指针实现 4.1.基础对象类4.2.辅助类4.3.为基础对象类实现智能指针类4.4.智能指针类的使用与测试 5.智能指针...
  • wonengguwozai
  • wonengguwozai
  • 2016年08月16日 10:29
  • 413

Android系统篇之----Android中的智能指针

一、前言今天我们开启Android系统篇的文章了,其实一直想弄,只是之前一直没有太多深入的了解,最近又把这块拿出来好好看了一下,所以想从新梳理一下,来看看Android中的这块知识,首先我们今天来看一...
  • jiangwei0910410003
  • jiangwei0910410003
  • 2016年05月03日 17:27
  • 9640

c++ 智能指针及 循环引用问题

c++智能指针介绍 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete,比如流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 delet...
  • gfsfg8545
  • gfsfg8545
  • 2014年04月07日 13:36
  • 8215

C++ — 智能指针的简单实现以及循环引用问题

智能指针
  • Dawn_sf
  • Dawn_sf
  • 2017年04月17日 17:14
  • 896

浅谈BOOST库里面的智能指针

大家都知道,学习C语言,指针很很重要的一部分,那么为什么在C11中还会出现智能指针的概念呢,我们都知道C11是将以前C99的知识进行了更加深入的改变,让C用起来更加的方便,而且它还创建了许多新的类型,...
  • km_1314107
  • km_1314107
  • 2017年07月19日 10:31
  • 306
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:两种智能指针-RAII智能指针和引用计数智能指针
举报原因:
原因补充:

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