是否可以编写一个自定义的 STL 分配器,它使用指向用户提供的分配函数的指针?
Is it possible to write a custom STL allocator that uses pointers to allocation functions provided by the user?
我们有一个库,它通过 extern "C"
提供 C 接口,并从 C 代码中使用,但为了方便起见,它内部使用了 STL 容器和一些 C++ 功能,如 RAII。
现在有一个新要求,即库应该能够从客户端代码中获取指向自定义 malloc
和 free
函数的指针,并将其用于内部分配。我可以将它们放入库的上下文结构中,并在需要的地方使用它们,但是将它们与 STL 一起使用是令人费解的...
我查看了分配器 类,但似乎 STL 容器必须能够使用默认构造函数来创建分配器,而且似乎没有办法将这些指针放入其中以让它们通过它们进行调用做分配。
是否可以最好以线程安全的方式(不使用全局变量)解决这个问题?
I looked at allocator classes but it seems STL containers must be able to use the default constructors to create the allocator
这不是真的,所有容器都可以显式地使用分配器构造,因此您可以创建分配器对象,然后将其传递给容器。
extern "C"
{
typedef void* (*allocation_function)(size_t);
typedef void (*deallocation_function)(void*);
}
template<typename T>
class Allocator
{
public:
typedef T value_type;
Allocator(allocation_function alloc, deallocation_function dealloc)
: m_allocate(alloc), m_deallocate(dealloc)
{ }
template<typename U>
Allocator(const Allocator<U>& a)
: m_allocate(a.m_allocate), m_deallocate(a.m_deallocate)
{ }
T* allocate(size_t n)
{ return static_cast<T*>(m_allocate(n * sizeof(T))); }
void deallocate(T* p, size_t)
{ m_deallocate(p); }
private:
template<typename U>
friend class Allocator<U>;
template<typename U>
friend bool operator==(const Allocator<U>&, const Allocator<U>&);
allocation_function m_allocate;
deallocation_function m_deallocate;
};
template<typename T>
bool operator==(const Allocator<T>& l, const Allocator<T>& r)
{ return l.m_allocate == r.m_allocate; }
template<typename T>
bool operator!=(const Allocator<T>& l, const Allocator<T>& r)
{ return !(l == r); }
Allocator<int> a(custom_malloc, custom_free);
std::vector<int, Allocator<int>> v(a);
如果您还没有使用 C++11,那么您需要为您的分配器提供更多的成员以满足旧的要求,但上面的成员对于 C++11 是可以的。在 C++03 中使用自定义分配器很困难,而且无论如何都不可移植,因此如果需要这样做,您应该以使用 C++11 编译器为目标。
由于分配器不能是全状态的,但必须是默认可构造的,我建议使用模板在编译时实例化分配器。
是的。例如,查看 header gc/gc_allocator.h
from Boehm garbage collector (you could easily replace the lower calls to GC_MALLOC
etc by some function pointers). See this answer.
我们有一个库,它通过 extern "C"
提供 C 接口,并从 C 代码中使用,但为了方便起见,它内部使用了 STL 容器和一些 C++ 功能,如 RAII。
现在有一个新要求,即库应该能够从客户端代码中获取指向自定义 malloc
和 free
函数的指针,并将其用于内部分配。我可以将它们放入库的上下文结构中,并在需要的地方使用它们,但是将它们与 STL 一起使用是令人费解的...
我查看了分配器 类,但似乎 STL 容器必须能够使用默认构造函数来创建分配器,而且似乎没有办法将这些指针放入其中以让它们通过它们进行调用做分配。
是否可以最好以线程安全的方式(不使用全局变量)解决这个问题?
I looked at allocator classes but it seems STL containers must be able to use the default constructors to create the allocator
这不是真的,所有容器都可以显式地使用分配器构造,因此您可以创建分配器对象,然后将其传递给容器。
extern "C"
{
typedef void* (*allocation_function)(size_t);
typedef void (*deallocation_function)(void*);
}
template<typename T>
class Allocator
{
public:
typedef T value_type;
Allocator(allocation_function alloc, deallocation_function dealloc)
: m_allocate(alloc), m_deallocate(dealloc)
{ }
template<typename U>
Allocator(const Allocator<U>& a)
: m_allocate(a.m_allocate), m_deallocate(a.m_deallocate)
{ }
T* allocate(size_t n)
{ return static_cast<T*>(m_allocate(n * sizeof(T))); }
void deallocate(T* p, size_t)
{ m_deallocate(p); }
private:
template<typename U>
friend class Allocator<U>;
template<typename U>
friend bool operator==(const Allocator<U>&, const Allocator<U>&);
allocation_function m_allocate;
deallocation_function m_deallocate;
};
template<typename T>
bool operator==(const Allocator<T>& l, const Allocator<T>& r)
{ return l.m_allocate == r.m_allocate; }
template<typename T>
bool operator!=(const Allocator<T>& l, const Allocator<T>& r)
{ return !(l == r); }
Allocator<int> a(custom_malloc, custom_free);
std::vector<int, Allocator<int>> v(a);
如果您还没有使用 C++11,那么您需要为您的分配器提供更多的成员以满足旧的要求,但上面的成员对于 C++11 是可以的。在 C++03 中使用自定义分配器很困难,而且无论如何都不可移植,因此如果需要这样做,您应该以使用 C++11 编译器为目标。
由于分配器不能是全状态的,但必须是默认可构造的,我建议使用模板在编译时实例化分配器。
是的。例如,查看 header gc/gc_allocator.h
from Boehm garbage collector (you could easily replace the lower calls to GC_MALLOC
etc by some function pointers). See this answer.