为 CHeapPtr 创建自定义分配器(用于 Sqlite)
Creating a custom allocator for CHeapPtr (for use with Sqlite)
我想使用 CHeapPtr
为 sqlite3
创建一些智能指针。 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);
}
};
现在我可以像这样创建 CHeapPtr
s:
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)
放在那里。
我想使用 CHeapPtr
为 sqlite3
创建一些智能指针。 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);
}
};
现在我可以像这样创建 CHeapPtr
s:
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)
放在那里。