http://unitygems.com/memorymanagement/
October 21, 2012
参照の作成
ここまで値型変数に対する参照を作成することが出来ることを見てきた。関数の中で整数を作成しつつ、後続で値を使用するために保持したいことを考慮する必要がある。単に関数の中で宣言を行うと自動変数の作成が行われ、関数の終了とともに値は破棄される。
スクリプトの中で、参照つきでヒープ上に動的に割り当てられる変数を作成できる。
using UnityEngine; using System.Collections; public class Test:MonoBehaviour{ int number; void Update () { if(Input.GetKeyDown (KeyCode.C)) CreateVariable(); if(Input.GetKeyDown (KeyCode.Space)) PrintVariable(number); } void CreateVariable(){ //int number = new int(); number = new int(); number = 10; print ("In function "+number); } void PrintVariable(int n){ print (n); n+=10; } }最初にint型のグローバル変数numberを宣言します。この変数をCreateVariable関数の中で使用し、int()を用いて整数の値参照を割り当てます。
状況を整理するために、newキーワードは、ヒープ上に作成される変数に対する参照を戻します。参照は、新規に作成された変数の番地を保持するnumberに格納されます。新規作成された変数は関数の外に存在しています。
コメントアウトされた箇所について、これを含めてしまうと関数が終了したタイミングで参照を失ってしまいます。ガーベージコレクションの次回処理するタイミングで、参照がなくなっていることが判明し、メモリから取り除かれます。ローカル変数を宣言するとき、関数のなかで整数numberに対して行ったときと同様に、グローバルの整数numberが隠されます。
intのようなプリミティブ変数を保持するとき、参照のなかでコンパイラはボクシングと呼ばれる、クラスの中のプリミティブ変数をラッピングする、関数を実行します。この方法で宣言された変数はヒープ上に割り当てられ、解放されたときに、ガーベージコレクションを発生させ、さらにデフォルトのプリミティブな変数よりもメモリを消費します。
基本的なボクシングの状況を想定してみます。Debug.log(object)関数を使用するとき、パラメータはどのような変数でも関数に渡すことが出来るという意味のオブジェクトです。整数を渡すとき、コンパイラはオブジェクトの中に整数を箱詰め(ボックス)します。次にボクシングを使用することによって、最適化することが出来ます:
void PrintingManyTimes(int n){ object obj = n; for(int i = 0;i<500;i++) Debug.Log(obj); }
このようにしてコンパイラはDebug.Logをコールする度にボクシングを行う必要がなくなります。一回の実行だけで、500コール全てに対応します。
-------
Unityメモリ管理の基礎を積み上げていこうぜ!
0 件のコメント:
コメントを投稿