第105章 std::experimental::pmr::memory_resource ( C++17 )

目次

105.1. memory_resource でアラインメントの実装(非実用的な実験です)

 memory_resource は実験的な新機能なのでテスト目的以外に利用すべきかは判断が分かれると思います。

 まあアロケーターを既に使っている人なんかには、不要だって言う人が多そうです。

 memory_resource の仕組みや実装は、インターフェースを実装するだけで済むのでアロケーターを作ったことがあれば難しくはないです。

 では簡単な実装例をみて見ましょう。

main.cpp. 

  1 #include <experimental/memory_resource>
  2 #include <experimental/vector>
  3 #include <iostream>
  4 #include <vector>
  5 #include <cstdlib>
  6
  7 template<typename T>
  8 class aligned_heap_allocator : public std::experimental::pmr::memory_resource
  9 {
 10   typedef std::size_t size_type;
 11   typedef T value_type;
 12   typedef value_type* pointer;
 13   typedef const value_type* const_pointer;
 14   typedef value_type& reference;
 15   typedef const value_type const_reference;
 16
 17 public:
 18   explicit aligned_heap_allocator() noexcept = default;
 19   explicit aligned_heap_allocator(const aligned_heap_allocator&)  {}
 20
 21   template<typename U>
 22   aligned_heap_allocator(const aligned_heap_allocator<U>&){}
 23
 24 protected:
 25   void *do_allocate(std::size_t n, std::size_t alignment = alignof(std::max_align_t)) override
 26   {
 27     return static_cast<void*>(std::aligned_alloc(alignment,n * sizeof(T)));
 28   }
 29
 30   void do_deallocate(void *p, size_t /* n */, std::size_t /* alignment */) override
 31   {
 32     std::free(p);
 33   }
 34
 35   bool do_is_equal(std::experimental::pmr::memory_resource const & other) const noexcept override
 36   {
 37     return this == &other;
 38   }
 39 };
 40
 41 int main()
 42 {
 43   aligned_heap_allocator<int> alloc;
 44   std::experimental::pmr::vector<int> vec({1},&alloc);
 45   vec.push_back(10);
 46   vec.push_back(20);
 47
 48   std::cout << vec[0] << " " << vec[1] << '\n';
 49
 50   vec.pop_back();
 51   vec.push_back(30);
 52
 53   for(auto const& x : vec)
 54     std::cout << x << " ";
 55   std::cout << '\n';
 56 }

ビルドと実行結果. 

$ g++ main.cpp -std=c++17
$ ./a.out
1 10
1 10 30

 ちなみにちょっとコードが汚くなってまして、すんません。

 次作を書きながらなので、完璧を目指すと爆死しそうなんで許してもらえると助かります。

 24 protected:
 25   void *do_allocate(std::size_t n, std::size_t alignment = alignof(std::max_align_t)) override
 26   {
 27     return static_cast<void*>(std::aligned_alloc(alignment,n * sizeof(T)));
 28   }
 29
 30   void do_deallocate(void *p, size_t /* n */, std::size_t /* alignment */) override
 31   {
 32     std::free(p);
 33   }
 34
 35   bool do_is_equal(std::experimental::pmr::memory_resource const & other) const noexcept override
 36   {
 37     return this == &other;
 38   }

 やってることは do_allocate() / do_deallocate() / do_is_equal() 関数をオーバーライドだけですよね。

 それと std::aligned_alloc も使ってますが、ここは malloc() でも new でもなんでも良いわけです。

Copyright 2018-2019, by Masaki Komatsu