ここでは、アクティベーション レコードとヒープ上のオブジェクトの 2 つが関係しています。
グローバル変数のアクティベーション フレームから始めます。
globArray : undefined
ヒープには、コードに表示されるリテラルが含まれています
ptr0 : "craig"
ptr1 : "silva"
、などはptr0
、ptr1
メモリ内の特定の場所を参照する単なるアドレスまたはラベルです。
を呼び出すtest()
と、インタープリターは、ローカル変数用のボックスを含む新しいアクティベーション フレームをプッシュします。
globArray : undefined
---------------------
names : undefined
次に、インタープリターは["craig", "silva"]
、ヒープ上にオブジェクトを作成するものを評価します。
ptr0 : "craig"
ptr1 : "silva"
ptr2 : [ &ptr0, &ptr1 ]
これptr2
は、2 つの値を指す配列を含むメモリ内の場所です。
このメモリの場所はnames
、アクティベーション レコード内の場所に格納されるようになったため、コール スタックは次のようになります。
globArray : undefined
---------------------
names : &ptr2
割り当てnames = ...
はヒープを変更せず、アクティベーション レコードのみを変更します。
次にglobArray = names
、1 つのアクティベーション レコード エントリの内容を別のエントリにコピーします。
globArray : &ptr2
---------------------
names : &ptr2
その後、 への呼び出しがtest
終了し、アクティベーション レコードが破棄されます。
globArray : &ptr2
ここで、global はglobArray
への呼び出し中に作成されたオブジェクトを指しますtest
。関数の最後は、ヒープではなく、アクティブなアクティベーション レコードを変更するだけなので、ヒープは次のようになります。
ptr0 : "craig"
ptr1 : "silva"
ptr2 : [ &ptr0, &ptr1 ]
ptr2
同じ配列のままです。
「名前」がなくなったのですね。
names
(アクティベーション レコードのエントリ) はなくなりましたが、アクティブなアクティベーション レコードのエントリによってまだポイントされているため、それが指していたオブジェクトはありませんglobArray
。
その後、test2 を呼び出しますが、要素が表示されます。したがって、オブジェクト全体をコピーする必要があります
いいえ、そのオブジェクトが占有するヒープ内の場所への参照をコピーしただけです。ヒープが変更されていないため、新しいオブジェクトは作成されず、ヒープはすべてのオブジェクトが作成される場所です。
スタックとヒープとは何ですか? 興味があるかもしれません。