65.9K
CodeProject 正在变化。 阅读更多。
Home

C++ 内存管理器

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.32/5 (15投票s)

2006年5月24日

CPOL

2分钟阅读

viewsIcon

48257

一个C++内存管理器,可以自动删除任何未使用的堆对象。

引言

我想到一个很酷的项目来尝试。结果就是这个C++内存管理器。它的目的是自动删除应用程序不再使用的堆对象。无需手动删除它们。更好的是 - 它会在不再需要时立即删除它们。你不需要等待指定的时间来删除对象,它也不会占用大量的处理器时间来跟踪和删除所有对象。这是一个简单但非常实用的类。好了,这是类的代码

#pragma once
#pragma warning ( disable: 4312 )

template<typename T> class CMemoryManager
{
private:
    template<typename T> class Pointer
    {
        friend class CMemoryManager;
        T* p;
        DWORD* pdwRefCount;
    public:
        template<typename Type> void operator = (Type value)
        { 
            *p = value;
        }
        template<typename Type> bool operator == (Type value)
        {
            return (*p == value);
        }
        operator T* () { return p; }
    };
    Pointer<T> p;
public:
    CMemoryManager()
    {
        Init();
    }
    CMemoryManager(T* pNew)
    {
        Init();
        SetNewPointer(pNew);
    }
    CMemoryManager(int val)
    {
        Init();
        SetNewPointer((T*)val);
    }
    CMemoryManager(const CMemoryManager& rmm)
    {
        Init();
        UpdateMemoryManager(rmm);
    }
    ~CMemoryManager() 
    { 
        if (p.pdwRefCount == NULL) return;
        if (*p.pdwRefCount == 0 || --(*p.pdwRefCount) == 0) 
        {
            delete p.p;
            delete p.pdwRefCount;
            Init();
        }
    }
    void Init()
    {
        p.pdwRefCount = NULL;
        p.p = NULL;
    }
    void AssignNewPointer(const T* pNew)
    {
        p.p = (T*)pNew;
    }
    void CheckRefCount()
    {
        if (p.pdwRefCount == NULL) NewRefCounter();
    }
    void SetRefCount(DWORD dwNewCount)
    {
        CheckRefCount();
        *p.pdwRefCount = dwNewCount;
    }
    void IncreaseRefCount()
    {
        CheckRefCount();
        (*p.pdwRefCount)++;
    }
    void NewRefCounter()
    {
        p.pdwRefCount = new DWORD;
        *p.pdwRefCount = 0;
    }
    void SetNewPointer(const T* pNew)
    {
        Delete();
        AssignNewPointer(pNew);
        IncreaseRefCount();
    }
    void Delete()
    {
        this->~CMemoryManager();
        Init();
    }
    void UpdateMemoryManager(const CMemoryManager& rmm)
    {
        Delete();
        AssignNewPointer(rmm.p.p);
        p.pdwRefCount = rmm.p.pdwRefCount;
        IncreaseRefCount();
    }
    void operator = (int val)
    {
        SetNewPointer((T*)val);
    }
    void operator = (const T* pmm)
    {
        SetNewPointer(pmm);
    }
    void operator = (const CMemoryManager* pmm)
    {
        UpdateMemoryManager(*prmm);
    }
    void operator = (const CMemoryManager& rmm)
    {
        UpdateMemoryManager((CMemoryManager&)rmm);
    }
    void SetNewAddr(T* pNewAddr, DWORD dwRefCount)
    {
        Delete();
        SetNewPointer(pNewAddr);
        SetRefCount(dwRefCount);
    }
    void Detach()
    {
        if (*p.pdwRefCount == 1) 
        {
            delete p.pdwRefCount;
            delete p.p;
        }
        p.pdwRefCount = NULL;
        p.p = NULL;
    }
    int GetSize() { return sizeof(*p.p); }
    Pointer<T>& operator * () { return p; }
    T* operator -> () { return p.p; }
    operator T* () { return p.p; }
    operator void* () { return p.p; }
    void operator delete(void* p) { }
    // Do nothing if attempting to delete the object.
    // Object will automatically be deleted by the class.

    T* GetPointer() { return p.p; }
    bool operator == (int nCompare) { return (p.p == (T*)nCompare); }
    operator bool () { return (p.p != NULL); }
};

#pragma warning ( default: 4312 )
#define pp CMemoryManager

你所要做的就是将所有堆内存封装在 CMemoryManager 类中。然后,你可以像它们没有被封装一样使用这些指针。或者,至少你应该这样做。试一试!看看它是如何工作的,并报告任何不工作的情况。我不知道 Visual Studio 2003 或更早版本中的 IntelliSense 是否能够真正检测到实际指针的类成员,但在 2005 版本中,它可以完美地工作。所以,再次强调,试一试,告诉我你的想法和它的工作情况。再也不用担心需要手动删除的指针了!另外请注意,不要对它们使用 "delete"。相反,如果你想释放指针,请调用成员方法 Delete。如果对象不再使用(引用计数为 0),则它将被释放。另外请记住始终使用容器。如果你将一个普通的指针分配给内存管理器,它将不会保持引用计数!所以,如果可能的话,始终分配实际的内存管理器对象。最后,不要使用这个类来封装你没有责任释放的内存指针。只在自己的内存上使用它。而且,我建议你只在自己分配的新对象上使用它。

我已经更新了这个类。它现在更有效率,也更好。据我所知,没有错误。

© . All rights reserved.