STL中的Allocator

一、 自定义allocator

1.1 需要实现的类型

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
  // ...
};

有的容器可能需要构造多种类型的allocator,比如hashmap的bucket,这时候就需要rebind:

typedef A::rebind<Node>::other  Node_Allocator;

1.2 相关函数

  • pointer address(reference r) const
    Returns the address of r as a pointer type. This function and the following function are used to convert references to pointers.

  • const_pointer address(const_reference r) const
    Returns the address of r as a const_pointer type.

  • pointer allocate(size_type n, allocator<U>::const_pointer hint=0)
    Allocates storage for n values of T. Uses the value of hint to optimize storage placement, if possible.

  • void deallocate(pointer)
    Deallocates storage obtained by a call to allocate.

  • size_type max_size()
    Returns the largest possible storage available through a call to allocate.

  • void construct(pointer p, const_reference val)
    Constructs an object of type T at the location of p, using the value of val in the call to the constructor for T.

  • void destroy(pointer p)
    Calls the destructor on the value pointed to by p.

1.3 实现

#include <stdio.h>
#include <new>
#include <cstddef>
#include <cstdlib>
#include <cstdlib>
#include <climits>
#include <vector>
#include <iostream>

using namespace std;

namespace jack{

template <typename T>
T* _allocate(ptrdiff_t size, T*) {
  set_new_handler(0);
  T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));
  if (!tmp) {
    cerr << "out of memory" << endl;
    exit(1);
  }
  return tmp;
}

template <typename T>
void _deallocate(T* buffer){
  ::operator delete(buffer);
}

template <typename T1, typename T2>
void _construct(T1 *p, const T2& value) {
  // placement new
  new(p) T1(value);
}

template <typename T>
inline void _destroy(T* ptr){
  ptr->~T();
}

template <typename T>
class allocator {
  public:
  using value_type = T;
  using pointer = T*;
  using const_pointer = const T*;
  using reference = T&;
  using const_reference = const T&;
  using size_type = size_t;
  using difference_type = ptrdiff_t;

  template <typename U>
  struct rebind {
    typedef allocator<U> other;
  };
  
  pointer allocate(size_type n, const void* hint=0) {
    printf("allocate %zu for type %s\n", n, typeid(T).name());
    return _allocate((difference_type)n, (pointer)0);
  }

  void deallocate(pointer p, size_type n) {
    printf("deallocate %zu for type %s\n", n, typeid(*p).name());
    _deallocate(p);
  }

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

  pointer address(reference x) {
        return (pointer)&x;
  }

  const_pointer address(const_reference x) {
        return (const_pointer)&x;
  }

  size_type max_size() const {
        return size_type(UINTMAX_MAX / sizeof(T));
  }
};
};

int main (int argc, char *argv[])
{
  vector<int, jack::allocator<int>> iv{1, 2, 3, 4, 5};
  return 0;
}

参考

  1. C++ STL应用与实现】95: 如何使用Allocator
  2. set_new_handler的作用
  3. placement new 和operator new
  4. Using Custom Allocators
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值