(转)C++ 实现内存自动托管的模板类

C++ 实现内存自动托管的模板类

C++ 2010-04-17 18:26:04 阅读45 评论0   字号: 订阅

文/Fenying

 

    使用Traits类特化实现内存的自动化托管,防止内存泄露。

 

    原理是在作用域结束后自动释放所有申请了托管的动态内存。

 

/************************************************************************
 * Safely Trusted Engine of Memory                                      *
 *                                                                      *
 * Language: C++ (ANSI 98 Standard)                                     *
 * Newest Version: 1.0                                                  *
 *                                                                      *
 * Author: Fenying                                                      *
 * Details: An class used to automatically manage memory.               *
 * CopyRight: All CopyRights Fenying Studio 2007 - 2009 Reserved.       *
 *                                                                      *
 * Version: 1.0                                                         *
 * Author: Fenying                                                      *
 * Time: 2009-10-23                                                     *
 * Details: http://fenying.blog.163.com                                 *
 ************************************************************************/

#ifndef VOID
    typedef unsigned int        UINT;
#endif

template < class TSTEM , bool bIsArray = false >
class CStem;

/*            Safely Trusted Engine of Memory Item            */

template < class TSTEM , bool bIsArray = false >
class CStemItem
{
public :

    friend    class CStem < TSTEM , bIsArray >;
    CStemItem( TSTEM * pItem)
    {
        m_pItem        = pItem;
        m_pPrevious = m_pNext = NULL;
    }

    ~ CStemItem()
    {
        if ( m_pPrevious != NULL)
            m_pPrevious -> m_pNext = m_pNext;

        if ( m_pNext != NULL)
            m_pNext -> m_pPrevious = m_pPrevious;

        if ( m_pItem != NULL)
            if ( bIsArray)
                delete [] m_pItem;
            else
                delete m_pItem;
    }

private :

    TSTEM                             * m_pItem;
    CStemItem < TSTEM , bIsArray >        * m_pNext;
    CStemItem < TSTEM , bIsArray >        * m_pPrevious;
};

/************************************************************************/

/*            Safely Trusted Engine of Memory            */

template < class TSTEM , bool bIsArray >
class CStem
{
public :

    CStem() {
        m_pFirstItem    = NULL;
        m_nCount        = 0;
    }

    ~ CStem() {
        FreeMemory();
    }

    TSTEM * New()
    {
        TSTEM * temp = new TSTEM;
        if ( temp)
            Trust( temp);
        return temp;
    }

    TSTEM * NewArray( UINT nArraySize)
    {
        if ( ! bIsArray)
            return NULL;

        TSTEM * temp = new TSTEM [ nArraySize ];
        if ( temp)
            Trust( temp);
        return temp;
    }

    void Trust( TSTEM * pItem)
    {
        if ( m_pFirstItem == NULL)
        {
            CStemItem < TSTEM , bIsArray > * pTemp = new CStemItem < TSTEM , bIsArray >( pItem);
            m_pFirstItem = pTemp;
            m_nCount ++;
        }
        else
        {
            CStemItem < TSTEM , bIsArray > * pTemp = new CStemItem < TSTEM , bIsArray >( pItem);
            pTemp -> m_pNext = m_pFirstItem;
            m_pFirstItem = pTemp;
            m_nCount ++;
        }
    }

    void UnTrust( TSTEM * pItem)
    {
        CStemItem < TSTEM , bIsArray > * T = m_pFirstItem;
        for ( UINT i = 0; i < m_nCount; i ++)
        {
            if ( T -> m_pItem != pItem)
                T = T -> m_pNext;
            else
            {
                delete T;
                m_nCount --;
                if ( ! m_nCount)
                    m_pFirstItem = NULL;
                break;
            }
        }
    }

    void FreeMemory()
    {
        if ( m_pFirstItem)
        {
            while ( m_pFirstItem)
            {
                CStemItem < TSTEM , bIsArray > * pTemp = m_pFirstItem -> m_pNext;
                delete m_pFirstItem;
                m_pFirstItem = pTemp;
            }
            m_pFirstItem = NULL;
            m_nCount = 0;
        }
    }

    UINT GetCount() const { return m_nCount ;}

private :

    CStemItem < TSTEM , bIsArray >    * m_pFirstItem;
    UINT                          m_nCount;
};

/************************************************************************/

 

    以上就是该类的完整代码。

 

    下面看使用实例。(VC++ 2008 Team System 下测试通过)

// test1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

/************************************************************************
 * Safely Trusted Engine of Memory                                      *
 *                                                                      *
 * Language: C++ (ANSI 98 Standard)                                     *
 * Newest Version: 1.0                                                  *
 *                                                                      *
 * Author: Fenying                                                      *
 * Details: An class used to automatically manage memory.               *
 * CopyRight: All CopyRights Fenying Studio 2007 - 2009 Reserved.       *
 *                                                                      *
 * Version: 1.0                                                         *
 * Author: Fenying                                                      *
 * Time: 2009-10-23                                                     *
 * Details: http://fenying.blog.163.com                                 *
 ************************************************************************/

#ifndef VOID
    typedef unsigned int        UINT;
#endif

template <class TSTEM, bool bIsArray = false>
class CStem;

/*            Safely Trusted Engine of Memory Item            */

template <class TSTEM, bool bIsArray = false>
class CStemItem
{
public:

    friend    class CStem<TSTEM, bIsArray>;
    CStemItem(TSTEM *pItem)
    {

        m_pItem        = pItem;
        m_pPrevious = m_pNext = NULL;
    }


    ~CStemItem()
    {

        if (m_pPrevious != NULL)
            m_pPrevious->m_pNext = m_pNext;

       
if (m_pNext != NULL)
            m_pNext->m_pPrevious = m_pPrevious;

       
if (m_pItem != NULL)
           
if (bIsArray)
               
delete []m_pItem;
           
else
                delete m_pItem;
    }


private:

    TSTEM                             *m_pItem;
    CStemItem<TSTEM, bIsArray>        *m_pNext;
    CStemItem<TSTEM, bIsArray>        *m_pPrevious;
};


/************************************************************************/

/*            Safely Trusted Engine of Memory            */

template <class TSTEM, bool bIsArray>
class CStem
{
public:

    CStem() {
        m_pFirstItem    = NULL;
        m_nCount        =
0;
    }


    ~CStem() {
        FreeMemory();
    }


    TSTEM *New()
    {

        TSTEM *temp = new TSTEM;
       
if (temp)
            Trust(temp);
       
return temp;
    }


    TSTEM *NewArray(UINT nArraySize)
    {

        if (!bIsArray)
           
return NULL;

        TSTEM *temp =
new TSTEM[nArraySize];
        if (temp)
            Trust(temp);
       
return temp;
    }


    void Trust(TSTEM *pItem)
    {

        if (m_pFirstItem == NULL)
        {

            CStemItem<TSTEM, bIsArray> *pTemp = new CStemItem<TSTEM, bIsArray>(pItem);
            m_pFirstItem = pTemp;
            m_nCount++;
        }

        else
        {
            CStemItem<TSTEM, bIsArray> *pTemp = new CStemItem<TSTEM, bIsArray>(pItem);
            pTemp->m_pNext = m_pFirstItem;
            m_pFirstItem = pTemp;
            m_nCount++;
        }

    }

    void UnTrust(TSTEM *pItem)
    {

        CStemItem<TSTEM, bIsArray> *T = m_pFirstItem;
       
for (UINT i = 0; i < m_nCount; i++)
        {

            if (T->m_pItem != pItem)
                T = T->m_pNext;
           
else
            {
                delete T;
                m_nCount--;
               
if (!m_nCount)
                    m_pFirstItem = NULL;
               
break;
            }

        }
    }

    void FreeMemory()
    {

        if (m_pFirstItem)
        {

            while (m_pFirstItem)
            {

                CStemItem<TSTEM, bIsArray> *pTemp = m_pFirstItem->m_pNext;
               
delete m_pFirstItem;
                m_pFirstItem = pTemp;
            }

            m_pFirstItem = NULL;
            m_nCount =
0;
        }

    }

    UINT GetCount() const {return m_nCount;}

private:

    CStemItem<TSTEM, bIsArray>    *m_pFirstItem;
    UINT                          m_nCount;
};


/************************************************************************/


void TestVariables()
{
    CStem < int > a;
    int * l;

    cout << "普通变量: /n/n     申请内存测试: /n/n ";
    if ( l = a . New()) //申请内存并自动托管
    {
        cout << "        申请内存成功. /n/n ";
        cout << "        当前托管内存块数量:" << a . GetCount() << " /n/n ";
        * l = 123;
        cout << "        *l(0x" << l << ") = " << * l << " /n/n ";
        a . UnTrust( l); //释放指定内存
        cout << "        指针l指向的内存块已经被释放. /n/n         当前托管内存块数量:" << a . GetCount() << " /n/n ";
    }
    else
        cout << "        申请内存失败. /n/n ";

    cout << "    托管内存测试: /n/n ";

    if ( l = new int)
    {
        a . Trust( l); //托管内存
        cout << "        当前托管内存块数量:" << a . GetCount() << " /n/n ";
        a . UnTrust( l);
        cout << "        指针l指向的内存块已经被释放. /n/n         当前托管内存块数量:" << a . GetCount() << " /n/n ";
    }
    else
        cout << "        申请内存失败. /n/n ";

    for ( int i = 0; i < 10; i ++)
        a . New();

    cout << "    批量测试: /n/n         当前托管内存块数量:" << a . GetCount() << " /n/n ";

    a . FreeMemory(); // 释放所有被托管的内存

    cout << "        被托管的所有内存块已经被释放. /n/n         当前托管内存块数量:" << a . GetCount() << " /n/n ";
}


void TestArray()
{
    CStem < char , true > a;
    char * g;
    cout << "数组: /n/n     申请内存测试: /n/n ";
    if ( g = a . NewArray( 3)) //创建数组,并自动托管
    {
        cout << "        申请内存成功. /n/n ";
        cout << "        当前托管内存块数量:" << a . GetCount() << " /n/n ";
        *( g + 1) = 'a';
        cout << "        *(g + 1)(0x" << ( int *)( g + 1) << ") = " << *( g + 1) << " /n/n ";
        a . UnTrust( g); // 释放指定内存
        cout << "        指针g指向的内存块已经被释放. /n/n         当前托管内存块数量:" << a . GetCount() << " /n/n ";
    }
    else
        cout << "        申请内存失败. /n/n ";

    cout << "    托管内存测试: /n/n ";

    if ( g = new char [ 5 ])
    {
        a . Trust( g); //托管内存
        cout << "        当前托管内存块数量:" << a . GetCount() << " /n/n ";
        a . UnTrust( g);
        cout << "        指针g指向的内存块已经被释放. /n/n         当前托管内存块数量:" << a . GetCount() << " /n/n ";
    }
    else
        cout << "        申请内存失败. /n/n ";

    for ( int i = 0; i < 10; i ++)
        a . NewArray( 15);

    cout << "    批量测试: /n/n         当前托管内存块数量:" << a . GetCount() << " /n/n ";

    a . FreeMemory(); //释放所有被托管的内存

    cout << "        被托管的所有内存块已经被释放. /n/n         当前托管内存块数量:" << a . GetCount() << " /n/n ";
}

int _tmain( int argc , _TCHAR * argv [])
{
    TestVariables();
    TestArray();

    return 0;
}

 

    仅此而已,就这么简单。

  • 1
    点赞
  • 1
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

zjz800800

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值