参照代入

MAXScript では、「参照代入」と呼ばれるタイプの割り当てが使用されます。たとえば、リテラルを書いて変数値を作成すると、値に使用するメモリが割り当てられ、値へのポインタまたは「参照」は値自体でなく変数の中に置かれます。変数の値を別の変数に代入する場合、値に使用するメモリへの参照は新しい変数の中に置かれます。変数の値を配列要素に代入するときや、その値を関数呼び出し引数として渡すときも同じです。どのような場合でも、参照は代入されるか渡されます。変数に新しい値を代入したり、変数がスコープから外れた場合、変数が含んでいた参照は解除されます。ある値のメモリへの参照をプログラムがすべて解除したときが、メモリをクリアするのに適したタイミングです。

参照代入は、値全体のメモリがコピーされ代入される「値代入」とは対照的です。値代入には参照代入よりも優れている点があります。それは、変数または配列要素が再代入されるごとに、古い値のメモリ スペースが速やかにクリアされるという点です。これは、古い値が固有で、その値を参照できないためです。他の変数が依然として同じ値をポイントしていることがあるため、参照代入ではシステムが最初の値のメモリ スペースをクリアできません。

HyperCard の HyperTalkSome のような一部のスクリプト言語ではコピーベースのアプローチをとりますが、効率が悪いだけでなく値共有障害があるため MAXScript には適しません。MAXScript のメモリをクリアするためのタスクが発生します。C や Pascal などのプログラミング言語では、値のメモリが不要になったときにメモリを明示的にクリアすることが必要ですが、これが同言語を使用する上で最も困難なプログラミング作業になります。Java のような最近のバリアントや、Lisp や Smalltalk などの一部の上級言語の場合、メモリは自動的にクリアされます。MAXScript にも同じ機能が備わっています。これについては「メモリの割り当てとガベージ コレクション」で説明しています。

変数の値を別の変数に代入する場合、値に使用するメモリへの参照は新しい変数の中に置かれます。このため、どちらの変数も実際は同じ値を参照しています。変数の 1 つに新しい値を割り当てた場合、その変数は新しい値への参照を含み、他の変数は以前の値への参照を含みます。通常は、両方の変数ではこの新しい値を参照しないため、これが望ましい状態です。ただし、point3 や配列など、値の合成による値が複数の変数で参照され、合成値のコンポーネントの 1 つに新しい値を割り当てた場合には、若干複雑になります。値を合成値のコンポーネントに代入する場合、新しい値は作成されません。したがって、合成値を参照するすべての変数は、同じ値をポイントしたままになり、変更された合成値を「参照」します。次のスクリプトには、このような場合の例を示します。

スクリプト

(
a= "hello world" -- create a string value, put reference in a
b=a -- put string’s reference in b
format "a=%; b=%\n" a b -- and print their values
b= "thanks for the fish" -- create a string value, put reference in b
format "a=%; b=%\n" a b -- print values - they are different
b=a -- put string’s reference from a in b
a[1]= "J" -- change a component value
format "a=%; b=%\n" a b -- print values - they are the same
a=b=[10,20,30] -- assign a point3 value reference to a and b
format "a=%; b=%\n" a b -- and print their values
a.x=-100 -- change a component value
format "a=%; b=%\n" a b -- print values - they are the same
)

出力

a=hello world; b=hello world
a=hello world; b=thanks for the fish
a=Jello world; b=Jello world
a=[10,20,30]; b=[10,20,30]
a=[-100,20,30]; b=[-100,20,30]
OK

上記のような動作が望ましいかどうかは、状況によって異なります。期待どおりの動作でない場合には、独立した値のコピーを作成するほとんどの値のタイプに対して、 copy() メソッドを定義します。

配列や構造体などの場合には、値に合成値が含まれている場合があります。作成されたコピーは、「シャロー コピー」と呼ばれ、値そのもの(配列)のコピーのみが作成されます。コピーは値の合成値(配列の要素)からは作成されません。

3ds Max 9 以降では、 deepCopy() と呼ばれる特殊なコピー メソッドを配列のコピーに使用できます。配列内のすべての合成値が作成されます。詳細は、MAXKey 値を参照してください。

関連事項