とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

割り当て子 std::allocator とか

STL―標準テンプレートライブラリによるC++プログラミング 第2版
最後のリファレンスにロギングありの割り当て子のコードが載ってた。これが最後の実習。std::allocator に全部委譲。転送関数をひたすら書き,途中にログ用のコード入れただけ。
VC++2008 のアロケータは2倍ずつ拡大するわけじゃないみたい。償却時間が何とかっていう効率の問題だと思われる。

// P442 logalloc.h
#include<memory>
#include<iostream>
template<typename T, typename Allocator = std::allocator<T> >
class logging_allocator
{
 Allocator allocator_;
public:
 typedef typename Allocator::size_type       size_type;
 typedef typename Allocator::difference_type difference_type;
 typedef typename Allocator::pointer         pointer;
 typedef typename Allocator::const_pointer   const_pointer;
 typedef typename Allocator::reference       reference;
 typedef typename Allocator::const_reference const_reference;
 typedef typename Allocator::value_type      value_type;
 template<typename U>
  struct rebind
 {
  typedef logging_allocator<
   U,
   typename Allocator::template rebind<U>::other
  > other;
 };
 logging_allocator()
 {}
 logging_allocator(const logging_allocator& la)
  : allocator_(la.allocator_)
 {}
 template<typename U>
  logging_allocator(const logging_allocator<
                     U,
                     typename Allocator::template rebind<U>::other
                    >& la)
 : allocator_(la.allocator_)
 {}
 ~logging_allocator()
 {}

 pointer address(reference x)const
 {
  return allocator_.address(x);
 }
 const_pointer address(const_reference x)const
 {
  return allocator_.address(x);
 }
 size_type max_size()const
 {
  return allocator_.max_size();
 }
 void construct(pointer p, const value_type& value)
 {
  return allocator_.construct(p, value);
 }
 void destroy(pointer p)
 {
  return allocator_.destroy(p);
 }
 pointer allocate(size_type n , const void* hint = 0)
 {
  using std::clog;
  const std::ios::fmtflags flags = clog.flags();
  clog << "allocate("
   << std::dec << n << ", "
   << std::hex << hint << ") = ";
  const pointer result = allocator_.allocate(n, hint);
  clog << result << std::endl;
  clog.setf(flags);
  return result;
 }
 void deallocate(pointer p, size_type n)
 {
  using std::clog;
  const std::ios::fmtflags flags = clog.flags();
  clog << "deallocate("
   << std::hex << p << ", "
   << std::dec << n << ")" << std::endl;
  allocator_.deallocate(p, n);
  clog.setf(flags);
 }
};
template<typename T, typename Allocator1,
         typename U, typename Allocator2>
 bool operator==(const logging_allocator<T, Allocator1>& x,
                 const logging_allocator<U, Allocator2>& y)
{
 return x.allocator_ == y.allocator_;
}
template<typename T, typename Allocator1,
         typename U, typename Allocator2>
 bool operator!=(const logging_allocator<T, Allocator1>& x,
                 const logging_allocator<U, Allocator2>& y)
{
 return x.allocator_ != y.allocator;
}

// P445 ex24-01.cpp
#include<iostream>
#include<vector>
template<typename Container>
 void insert(Container& c)
{
 for(int i = 0; i < 10; i++){
  std::cout << " Inserting " << i << std::endl;
  c.push_back(i);
 }
 std::cout << "-- Done. --" << std::endl;
}
int main(){
 using std::cout;
 using std::endl;
 using std::vector;
 cout << "Demonstrating use of a custom allocator.\n"
  "-- Default allocator --" << endl;
 vector<int> v1;
 insert(v1);

 cout << "-- Custom allocator --" << endl;
 vector<int, logging_allocator<int> > v2;
 insert(v2);

 cout << "-- Custom allocator with reserve -- " << endl;
 vector<int, logging_allocator<int> > v3;
 v3.reserve(10);
 insert(v3);
}

実行例:

Demonstrating use of a custom allocator.
-- Default allocator --
 Inserting 0
 Inserting 1
 Inserting 2
 Inserting 3
 Inserting 4
 Inserting 5
 Inserting 6
 Inserting 7
 Inserting 8
 Inserting 9
-- Done. --
-- Custom allocator --
 Inserting 0
allocate(1, 00000000) = 003963D0
 Inserting 1
allocate(2, 00000000) = 00396618
deallocate(003963D0, 1)
 Inserting 2
allocate(3, 00000000) = 003963D0
deallocate(00396618, 2)
 Inserting 3
allocate(4, 00000000) = 00396618
deallocate(003963D0, 3)
 Inserting 4
allocate(6, 00000000) = 003963D0
deallocate(00396618, 4)
 Inserting 5
 Inserting 6
allocate(9, 00000000) = 00396618
deallocate(003963D0, 6)
 Inserting 7
 Inserting 8
 Inserting 9
allocate(13, 00000000) = 00396678
deallocate(00396618, 9)
-- Done. --
-- Custom allocator with reserve --
allocate(10, 00000000) = 003966E8
 Inserting 0
 Inserting 1
 Inserting 2
 Inserting 3
 Inserting 4
 Inserting 5
 Inserting 6
 Inserting 7
 Inserting 8
 Inserting 9
-- Done. --