RIGHT:[[▲>../]]

*はじめに [#uda107e4]

一言で言うと、Delphiの動的配列は''参照カウンタつきポインタ''です。
それ以上でもそれ以下でも無いです。

スコープが外れると自動的に開放してくれるので「string のようなものだ」と思っていると痛い目に合います。
「代入したときは参照カウンタをインクリメント」してくれ、
「スコープが外れたときは、参照カウンタをデクリメントし、0になったら自動的に開放」はしますが、「書き換えた時にコピー(copy on write)」はしてくれないのです。


いや、まあ、この辺のことは、ヘルプの「動的配列」のところに書いてあるんですが。

*検証例 [#radeb209]

**ソースコード [#e8d9713e]

 program dynarray;
 
 {$APPTYPE CONSOLE}
 uses
   Windows, Types;
 
 const DefaultLength = 10;
 
 procedure PrintArray(const aMessage: string; const aArray: TIntegerDynArray);
 var i: Integer;
 begin
   Write(aMessage);
   for i := Low(aArray) to High(aArray) do
     Write(aArray[i],  ' ');
   Writeln;
 end;
 
 procedure DynamicArrayTest;
 var
   i: Integer;
   Array1, Array2: TIntegerDynArray;
 begin
   // array1の確保と変更
   SetLength(Array1, DefaultLength);
   for i := Low(Array1) to High(Array1) do
     Array1[i] := i;
   // array1 を array2 にコピー
   Array2 := Array1;
   Writeln('array1 を array2 に直接代入');
   PrintArray(' Array1: ', Array1);
   PrintArray(' Array2: ', Array2);
 
   // array2 を変更
   for i := Low(Array2) to High(Array2) do
     Array2[i] := 1;
   Writeln('array2 を変更');
   PrintArray(' Array1: ', Array1);
   PrintArray(' Array2: ', Array2);
 
   // array1 を変更
   for i := Low(Array1) to High(Array1) do
     Array1[i] := 2;
   Writeln('array1 を変更');
   PrintArray(' Array1: ', Array1);
   PrintArray(' Array2: ', Array2);
 
   // array2 を確保と変更
   SetLength(Array2, DefaultLength);
   for i := Low(Array2) to High(Array2) do
     Array2[i] := 3;
   Writeln('array2 を確保し、変更');
   PrintArray(' Array1: ', Array1);
   PrintArray(' Array2: ', Array2);
 end;
 
 begin
   DynamicArrayTest;
 end.

**出力例 [#u24b6116]

 > dynarray.exe 
 array1 を array2 に直接代入
  Array1: 0 1 2 3 4 5 6 7 8 9 
  Array2: 0 1 2 3 4 5 6 7 8 9 
 array2 を変更
  Array1: 1 1 1 1 1 1 1 1 1 1 
  Array2: 1 1 1 1 1 1 1 1 1 1 
 array1 を変更
  Array1: 2 2 2 2 2 2 2 2 2 2 
  Array2: 2 2 2 2 2 2 2 2 2 2 
 array2 を確保し、変更
  Array1: 2 2 2 2 2 2 2 2 2 2 
  Array2: 3 3 3 3 3 3 3 3 3 3 

arrya2 を変更すると、array1まで変わっています。
また array1 を変更すると、array2まで変わっています。
これが stringになると、copy on writeが働いて、array2 を変更しても、
array1 は変わらないわけですね

当然ながらarray2を別に再確保した場合は、変更しても array1に影響していません。

*対策 [#mdd07957]

SetLengthして for ループで1つ1つコピーしてもいいのですが、面倒ですので、
copyを使います。

 array2 := copy(array1, 0, Length(array1));

*参考リンク [#k5ce4467]
-http://web.archive.org/web/20040222135820/http://kakinotane.s7.xrea.com/obj/ml001.html
うわー、ここのページまとまってて便利ですわー。


----
-"// array1" を変更 のところで、array1でなくarray2に代入していたのを修正 -- [[TOBY]] SIZE(10){2003-08-12 (火) 07:11:20}
- array of IntegerをTIntegerDynArrayに修正 -- [[TOBY]] &new{2008-10-21 (Tue) 16:23:02};
- Glömde jag säga att det är den bästa sidan i Sverige med hockeysnack.Det är uppdateringar hela tiden,hur hinner du :-Orfolst)ömare -- [[Johannah]] &new{2017-01-24 (Tue) 15:17:16};

#comment

TIME:"2017-01-24 (Tue) 15:17:16" REFERER:"http://tobysoft.net/wiki/index.php?Delphi%2F%C6%B0%C5%AA%C7%DB%CE%F3%A4%CE%E6%AB" USER_AGENT:"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0"
Front page   Edit Diff Backup Upload Copy Rename Reload   New Pages Search Recent changes   Help   RSS of recent changes