STL容器自定义内存分配器
Posted 双锅首上
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STL容器自定义内存分配器相关的知识,希望对你有一定的参考价值。
STL 和 STL 扩展类现在接受额外的模板分配器参数。分配器参数的默认值来自C++标准库std::allocator<T>。您也可以提供自己的分配器,以便在应用程序中自定义内存管理。为了提供您自己的模板类作为分配器,模板必须符合特定接口,包括成员函数和类型定义以及其句法和语义要求。
下面是一个简单的分配器的部分代码片段:
template <class T>
class my_allocator
{
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template <class U>
struct rebind { typedef allocator<U> other; };
// remaining member functions described below
// ...
};
rebind成员允许容器为某些任意数据类型构建分配器,分配器类型由模板参数确定。例如,容器可能需要分配 T 以外的类型(比如list节点或hash buckets)。在这种情况下,容器可以获得正确的类型,通常使用typedef:
typedef A::rebind<Node>::other Node_Allocator;
分配器模板类需满足上述要求。另外还需要实现下列函数:
构造函数
my_allocator() throw();
my_allocator (const allocator&) throw ();
template <class U>
my_allocator(const my_allocator<U>&);
析构函数
~my_allocator();
分配运算符
template <class U>
my_allocator& operator=(const my_allocator<U>&) throw();
public成员函数
pointer address(reference r) const;
返回一个指针类型的地址。此函数和下面这个函数用于将引用r转换为指针。
const_pointer address(const_reference r) const;
pointer allocate(size_type n,
allocator<U>::const_pointer hint=0);
分配n个值的存储空间。如果可以,使用hint的值优化存储位置。
void deallocate(pointer);
析构一块存储空间(和allocate是成对的)。
size_type max_size();
返回最大的可用存储空间(allocate可用的存储空间)。
void construct(pointer p, const_reference val);
在特定位置(p的位置)构造类(模板参数T)的对象,并在调用T的构造函数时使用val的值。
void destroy(pointer p);
对p指向的值调用析构函数。
下面的示例定义了一个简单的自定义分配器。这可以用来测试编译器或标准C++库对自定义分配器的支持。它检查代码中传递的分配器参数是否实际使用:
#include <rw/tvdlist.h>
#include <rw/cstring.h>
#include <iostream>
template <class T>
class my_allocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
my_allocator() {}
my_allocator(const my_allocator&) {}
pointer allocate(size_type n, const void * = 0) {
T* t = (T*) malloc(n * sizeof(T));
std::cout
<< " used my_allocator to allocate at address "
<< t << " (+)" << std::endl;
return t;
}
void deallocate(void* p, size_type) {
if (p) {
free(p);
std::cout
<< " used my_allocator to deallocate at address "
<< p << " (-)" <<
std::endl;
}
}
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
my_allocator<T>& operator=(const my_allocator&) { return *this; }
void construct(pointer p, const T& val)
{ new ((T*) p) T(val); }
void destroy(pointer p) { p->~T(); }
size_type max_size() const { return size_t(-1); }
template <class U>
struct rebind { typedef my_allocator<U> other; };
template <class U>
my_allocator(const my_allocator<U>&) {}
template <class U>
my_allocator& operator=(const my_allocator<U>&) { return *this; }
};
int main()
{
const int numItems = 100;
std::cout << "\\nCreating a RWTValDlist with a default allocator"
<< std::endl;
RWTValDlist<RWCString> regular;
std::cout << "\\nInserting " << numItems
<< " items" << std::endl;
for (int i = 0; i < numItems; ++i) {
regular.insert(RWCString('a' + i, i));
}
std::cout << "\\n\\nCreating a RWTValDlist with my_allocator type"
<< std::endl;
RWTValDlist<RWCString, my_allocator<RWCString> > custom;
std::cout << "\\nInserting " << numItems
<< " items\\n" << std::endl;
for (int i = 0; i < numItems; ++i) {
custom.insert(RWCString('a' + i, i));
}
return 0;
}
程序输出:
Creating a RWTValDlist with a default allocator
Inserting 100 items
Creating a RWTValDlist with my_allocator type
used my_allocator to allocate at address 0080ABD0 (+)
used my_allocator to allocate at address 0080AC08 (+)
Inserting 100 items
used my_allocator to allocate at address 0080AC40 (+)
used my_allocator to allocate at address 0080AC78 (+)
used my_allocator to allocate at address 0080C6F0 (+)
used my_allocator to allocate at address 0080C728 (+)
used my_allocator to allocate at address 0080FB28 (+)
used my_allocator to allocate at address 00820068 (+)
used my_allocator to deallocate at address 00820068 (-)
used my_allocator to deallocate at address 0080FB28 (-)
used my_allocator to deallocate at address 0080C728 (-)
used my_allocator to deallocate at address 0080C6F0 (-)
used my_allocator to deallocate at address 0080AC78 (-)
used my_allocator to deallocate at address 0080AC40 (-)
used my_allocator to deallocate at address 0080AC08 (-)
used my_allocator to deallocate at address 0080ABD0 (-)
可以看到,当没有使用自定义分配器时,正常创建了RWTValDist并插入了100个项。当使用my_allocator实例化列表时,my_allocator的实例被用于堆内存的8次分配和解分配。
以上是关于STL容器自定义内存分配器的主要内容,如果未能解决你的问题,请参考以下文章