山崎のC++日記:アロケータ練習2

アバター
山崎
記事: 2
登録日時: 15年前
住所: 北関東

山崎のC++日記:アロケータ練習2

投稿記事 by 山崎 » 14年前

普段から「だ・である」調で文章を書いているので、「です・ます」調で文章を書くと何を言いたい文なのか分からなくなってしまうという弊害に昨日気付かされた。少し淡々となってしまうとは思うが、今回から「だ・である」調で文章を書かせて頂こうと思う。

前回のアロケータの日記に、placement newについて詳しくコメント頂いたISLeさんにこの場を借りて再度お礼申し上げたいと思う。

さて、今回も前回の日記に引き続き、素人のアロケータ奮闘記を書きたい。前回は「なぜアロケータに興味を持ったか」を簡単に書いたので、今回は本当にアロケータが必要なのか、その疑問を書きたいと思う。

私はゲーム中に出現するキャラクター、敵、弾などのオブジェクトに共通するメンバやメソッドを基底クラスObjectにまとめ、必要に応じて「プレイヤーキャラクタークラス」や「弾クラス」としてObjectクラスを継承させている。Objectクラス型のリスト構造に主人公や敵弾などのオブジェクトを全て挿入し、先頭から動きの制御や描画を行うという手法をとっている。この「全てのオブジェクトを一括管理するクラス」に、私はいつもObjectManagerというクラス名をつけている。

敵キャラが敵弾を撃つときは、newによって生成した敵弾をObjectManagerに挿入し、処理や描画、メモリの解放も全てObjectManagerに任せきりにしている。敵弾は役目を終えれば「自分を解放してもいいよ」というフラグが立ち、それに気づいたObjectManagerはその敵弾を解放する、という仕組みである。この方式をとれば敵弾を放った敵キャラと敵弾の依存性を薄くすることができ、好きなだけ敵弾を撃っては後のメモリ管理をObjectManagerに押し付けることができる。敵弾がプレイヤーに向かって飛んで行っている最中に、その弾を撃ちだした敵キャラがObjectManagerから削除されても問題無いのが大きな利点だ。もちろん、通常のnewで大量の敵弾を生成していては、弾を打ち出すたびに処理落ちが発生する。

この処理落ちをどうにかするため、私はplacement newにを使ったアロケータに非常に興味があった。とりあえずステージ移動などプレイヤーの操作が一瞬止まる隙に十分な量の敵弾用のメモリを確保しておき、敵弾用のメモリはそのメモリプールから取ってくることによってnewとdeleteの高速化を図る。

しかしよく考えてみると、「それをplacement newで実装する必要が本当にあるのか?」という疑問が湧いてきた。

敵弾は敵キャラのメンバとして十分なサイズの配列として用意しておき、必要に応じてObjectManagerに敵弾のポインタを渡し、役目が終わった敵弾は解放するのではなくObjectManagerから外すだけにする。そうすれば、いちいちアロケータを実装する必要性は薄くなるのではないか、こんな疑問が湧いてきたのである。

ただそれだけでは、先ほど利点として述べた「弾が飛んでいる最中に、その弾をメンバとして持つ敵キャラが撃破されてObjectManagerから削除されたとき、一緒に削除された弾にObjectManagerがアクセスしてしまいエラーを起こす」という問題が残る。すぐには解決策が浮かんでこないが、何とかそれさえ直せればアロケータを作る必要性が殆どなくなるように思えてきたのである。

今は本業の研究が忙しく、アロケータを試しに実装してみる余裕が無いので疑問やアイデアだけがモヤモヤと頭の中を行ったり来たりしている。

ISLe
記事: 2650
登録日時: 15年前

Re: 山崎のC++日記:アロケータ練習2

投稿記事 by ISLe » 14年前

敵弾のアロケータは敵弾クラスに実装するのが良いと思います。
汎用のアロケータをセットして使うようにすれば種類の違うオブジェクト間で共有もできます。

アバター
Ciel
記事: 252
登録日時: 15年前

Re: 山崎のC++日記:アロケータ練習2

投稿記事 by Ciel » 14年前

今私はC++でシューティングを作り直そうとしているんですが、山崎さんがやられてる方法は、ほとんど私と同じ方法ですねw
これで処理落ちするのであれば、私も別の方法を考えないといけませんね^^;