前に意気揚々とアロケータを作った記事をUPしたのですが、unique_ptrで利用しようとするとカスタムデリータを実装する必要がありました。
ん?カスタムデリータ・・・・・・?初耳だなぁ(;^ω^)
■とりあえずunique_ptrでアロケータ使ってみる
デリータを指定しない欠陥プログラムをとりあえず書いてみる。(ちなみに今回はchar型配列を使おうとしています。)
std::stack_tagged_blocks_allocator<char> allocator; std::unique_ptr<char[]> hoge{allocator.allocate(buffer_size)};
これだと、unique_ptrはallocatorで確保されたメモリだとは知らないので解放時にエラーが出ます。
だからunique_ptrに確保したメモリを解放する関数オブジェクト(デリータ)を渡す必要があります。
■アロケータをデリータに対応する
デリータは構造体かクラスを用意して、渡されたポインタを解放する関数void operator()(T* p)を実装すればいいようです。()のオーバーロードです。
ただ、今回作った自作アロケータ・・・・・・deallocate関数の引数に取得時のサイズを入れないといけない設計だったんですよね・・・・・・orz
ということで、取得サイズの情報がポインタアドレスからわかるように割り当て時のブロックの構成を↓から
←前[header_flag:4byte][header_size:4byte][padding:?byte][allocated_size:?byte][footer:4byte]後→
↓に修正しました。
←前[header_flag:4byte][padding:?byte][header_size:4byte][allocated_size:?byte][footer:4byte]後→
それから、void operator()(T* p)だけの構造体を用意する方法もあるみたいですが、自分の場合は自作アロケータに直接デリータを実装しました。
■unique_ptrに作成したデリータを渡してみる
std::function<void(char*)>をテンプレートパラメータの第二引数に指定し、初期化します。
std::stack_tagged_blocks_allocator<char> allocator; std::unique_ptr<char[], std::function<void(char*)>> dest{allocator.allocate(buffer_size), std::stack_tagged_blocks_allocator<char>{}};
これで無事カスタムデリータを使って解放されるようになりました!めでたし
マルチスレッドでファイルを読み取る関数も作ったのでロード待ちの時間なんかを軽減できたらいいなーと思ってます。
■今週のゲーム制作:続・明日、初めて彼女と❤の機能を移植
ということで頑張っていきますぞ~!