为 CHeapPtr 创建自定义分配器(用于 Sqlite)

Creating a custom allocator for CHeapPtr (for use with Sqlite)

我想使用 CHeapPtrsqlite3 创建一些智能指针。 CHeapPtr 默认使用 CCRTAllocator class,所以我想我只是创建一些自定义分配器 class 继承自 CCRTAllocator 但覆盖它的 Free 方法,以便他们使用正确的清理功能:

class CSqlite3Allocator : public CCRTAllocator
{
public:
    static void Free(_In_ sqlite3* p) throw()
    {
        sqlite3_close_v2(p);
    }
};

class CSqlite3StmtAllocator : public CCRTAllocator
{
public:
    static void Free(_In_ sqlite3_stmt* p) throw()
    {
        sqlite3_finalize(p);
    }
};

现在我可以像这样创建 CHeapPtrs:

CHeapPtr<sqlite3, CSqlite3Allocator> psqlite;
CHeapPtr<sqlite3_stmt, CSqlite3StmtAllocator> pstmt;

这些指针似乎工作正常,并且似乎正在调用它们的清理方法。我只是想知道这是否是执行此操作的正确方法,或者是否有更可接受的创建自定义 CHeapPtr 的方法。感谢您的任何输入。

您不需要从 CCRTAllocator 继承,allocator 应该只是一个新的 class。您可以使用 ATL 的 COM heap allocator 作为示例:

class CComAllocator 
{
public:
    static void* Reallocate(void* p, size_t nBytes) throw()
    {
        return ::CoTaskMemRealloc(p, ULONG(nBytes));
    }
    static void* Allocate(size_t nBytes) throw()
    {
        return ::CoTaskMemAlloc(ULONG(nBytes));
    }
    static void Free(void* p) throw()
    {
        ::CoTaskMemFree(p);
    }
};

template <typename T>
class CComHeapPtr :
    public CHeapPtr<T, CComAllocator>
{
public:
    CComHeapPtr() throw()
    {
    }

    explicit CComHeapPtr(T* pData) throw() :
        CHeapPtr<T, CComAllocator>(pData)
    {
    }
};

(为简洁起见,这里的代码缩短了一点)

您的实施方式可以解决问题,但您从 CRT 继承了 allocation/reallocation 方法,这使它成为一个危险的组合:无意中您可能会得到 CRT Allocate 和 sqlite Free并且可能很难确定。如果您不打算使用分配方法,您可以将它们存根或将 ATLASSERT(FALSE) 放在那里。