当前位置:网站首页>STL容器自定义内存分配器
STL容器自定义内存分配器
2022-08-02 14:07:00 【3A是个坏同志】
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次分配和解分配。
边栏推荐
猜你喜欢
随机推荐
再见篇:App专项技术优化
可以拖拽的ViewGroup,仿微信拖拽缩放关闭
Win10不能启动WampServer图标呈橘黄色的解决方法
详解RecyclerView系列文章目录
Hession使用
一文带你快速掌握Kotlin核心技能
LLVM系列第二十五章:简单统计一下LLVM源码行数
【目标检测】YOLO v5 安全帽检测识别项目模型
IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but
UIWindow的makeKeyAndVisible不调用rootviewController 的viewDidLoad的问题
拥抱Jetpack之印象篇
文本匹配任务
VS Code无法安装插件之Unable to install because, the extension '' compatible with current version
spark写sql的方式
芝诺悖论的理解
关于UDF
7.如何给RecyclerView添加Click和LongClick事件
使用flutter小记
1. What is RecyclerView
想做好分布式架构?这个知识点一定要理解透彻









