IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++: STL内存分配器--allocator -> 正文阅读

[C++知识库]C++: STL内存分配器--allocator

**STL内存分配器--allocator**


一、STL内存分配器

分配器(allocator))是C ++标准库的一个组件, 主要用来处理所有给定容器(vector,list,map等)内存的分配和释放。C ++标准库提供了默认使用的通用分配器std::allocator,但开发者可以自定义分配器。
GNU STL除了提供默认分配器,还提供了__pool_alloc、__mt_alloc、array_allocator、malloc_allocator 内存分配器。
__pool_alloc :SGI内存池分配器
__mt_alloc : 多线程内存池分配器
array_allocator : 全局内存分配,只分配不释放,交给系统来释放
malloc_allocator :堆std::malloc和std::free进行的封装

二、STL allocator

1、STL allocator简介
new会分配内存并执行对象构造函数,delete会执行对象析构函数并释放内存。如果将内存分配和对象构造分离,可以先分配大块内存,只在需要时才真正执行对象构造函数。
STL在头文件memory中提供了一个allocator类,允许将分配和对象构造分离,提供更好的性能和更灵活的内存管理能力。为了定义一个allocator对象,必须指明allocator可以分配的对象类型。当allocator分配内存时,会根据给定的对象类型来确定恰当的内存大小和对齐位置。

  template<typename _Tp>
    class allocator : public __allocator_base<_Tp>
    {
   public:
      typedef size_t     size_type;
      typedef ptrdiff_t  difference_type;
      typedef _Tp*       pointer;
      typedef const _Tp* const_pointer;
      typedef _Tp&       reference;
      typedef const _Tp& const_reference;
      typedef _Tp        value_type;

      template<typename _Tp1>
	struct rebind
	{ typedef allocator<_Tp1> other; };


      allocator() throw() { }

      allocator(const allocator& __a) throw()
      : __allocator_base<_Tp>(__a) { }

      template<typename _Tp1>
	allocator(const allocator<_Tp1>&) throw() { }

      ~allocator() throw() { }

      // Inherit everything else.
    };

根据C++标准规范,STL中分配器的对外接口、成员变量都一样,只是接口内部实现有区别。
allocator实现在模板类new_allocator中:

  template<typename _Tp>
  class new_allocator
    {
    public:
      typedef _Tp*       pointer;
      typedef const _Tp* const_pointer;

      // NB: __n is permitted to be 0.  The C++ standard says nothing
      // about what the return value is when __n == 0.
      pointer
      allocate(size_type __n, const void* = 0)
      { 
		if (__n > this->max_size())
	  std::__throw_bad_alloc();

	return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
      }

      // __p is not permitted to be a null pointer.
      void
      deallocate(pointer __p, size_type)
      { ::operator delete(__p); }
    };

STL中容器默认分配器为std::allocator<_Tp>,内存分配和释放的接口allocate和deallocate内部实现只是将::operator new和::operator delete进行封装,没用做特殊处理。

3、STL allocator实例

#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;

class base
{
    public:
	     base(){  cout << "base ctor" << endl; }
        ~base(){  cout << "base dtor" << endl; }
        base(const base &t){cout << "Copy ctor" << endl; }
};

int main(int argc, const char *argv[])
{
    new_allocator<base> alloc_test;

    base *ptest = alloc_test.allocate(3);
    {
    	alloc_test.construct(ptest , base());
        alloc_test.construct(ptest + 1, base());
        alloc_test.construct(ptest + 2, base());
    }
    alloc_test.destroy(ptest);
    alloc_test.destroy(ptest + 1);
    alloc_test.destroy(ptest + 2);
    alloc_test.deallocate(ptest , 3);
    getchar();
    return 0;
}
-----------------------------------
// output:
//base ctor
//Copy ctor
//base dtor
//base ctor
//Copy ctor
//base dtor
//base ctor
//Copy ctor
//base dtor
//base dtor
//base dtor
//base dtor

4、自定义allocator
实现Allocator只需要实现allocate和deallocate,来实现自己的内存分配策略。

template<class T >
inline T*_allocate(ptrdiff_t num,T*){
    std::cout<<"_allocate"<<endl;
    return static_cast<T*>(::operator new(num*sizeof(T)));
}
template <class T>
inline void _deallocate(T* buff){
    std::cout<<"_deallocate"<<endl;
    ::operator delete(buff);
}

template <class T ,class U>
inline void _construct(T* p,const U& value){
    new(p)T(value);
}
template<class T>
inline void _destory(T* p){
    p->~T();
}
template<typename T>
class MyAlloctor{
    public:
        typedef T        value_type;
        typedef T*       pointer;
        typedef T&       reference;
        typedef const T* const_pointer;
        typedef const T& const_reference;
        typedef size_t     size_type;
        typedef ptrdiff_t  difference_type;
        template<typename _Tp1>struct rebind{ typedef allocator<_Tp1> other; };

    MyAlloctor()=default;
    ~MyAlloctor()=default;
    pointer address(reference x){
        return static_cast<pointer>(&x);
    }
    const_pointer address(const_reference x){
        return static_cast<const_pointer>(&x);
    }

    pointer allocate(size_type _n,const void* hit=0 ){
        return _allocate(_n,(pointer)0);
    }

    void deallocate(pointer p,size_type _n){
        _dealloctor(p);
    }

    size_type max_size()const throw(){
        return static_cast<size_type>(INT_MAX/sizeof(T));
    }

    void construct(pointer p,const_reference value){
        _construct(p,value);
    }

    void destroy(pointer p){
        _destory(p);
    }

};

测试代码:

#include <string>
#include <vector>
#include <iostream>
using namespace std;

class Base
{
public:
    Base()
    {
       cout << "Base ctor" << endl;
    }
    Base(const Base& other)
    {
       cout << "Base Copy ctor" << endl;
    }
    ~Base()
    {
       cout << "Base dtor" << endl;
    }
};

class Drive:Base
{
public:
    Drive()
    {
       cout << "Drivector" << endl;
    }
    Drive(const Drive& other)
    {
       cout << "Drive Copy ctor" << endl;
    }
    ~Drive()
    {
       cout << "Drive dtor" << endl;
    }
};


int main(void)
{

    vector<string, Myallocator<string> > vec(10, "test");

    vec.push_back("test1");
    vec.push_back("test2");

    Myallocator<Base>::rebind<Drive>::other alloc_test;
    Drive*p1 = alloc_test.allocate(5);
    alloc_test.construct(p1, Test2());
    alloc_test.construct(p1 + 1, Test2());
    alloc_test.construct(p1 + 2, Test2());

    alloc_test.destroy(p1);
    alloc_test.destroy(p1 + 1);
    alloc_test.destroy(p1 + 2);
    alloc_test.deallocate(p1, 3);

    return 0;
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-11 15:32:36  更:2021-12-11 15:34:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:49:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码