喫茶XRAYトップページ

[スレッド全体
]

[9927] 今更きけない 動的配列…(いや、まぁ聞くんだけどさ)返信 削除
2016/5/15 (日) 19:47:35 taki
マスター 教えてください。
動的配列を使う度に、以下の記事が気になって心配になります。

------------------------------------------
Delphi/動的配列の罠
http://tobysoft.net/wiki/index.php?Delphi%2F%C6%B0%C5%AA%C7%DB%CE%F3%A4%CE%E6%AB

動的配列を「string のようなものだ」と思っていると痛い目に合います。
動的配列は参照カウンタつきポインタ

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

説明はヘルプの「動的配列」のところに書いてあるそうなのですが、
Delphi XP4 Starter のHELPでキーワードに動的配列を入力しても説明が
見つかりません。

記事の説明のコードを見ると、単純に := で代入をするとポインタが
コピーされるので、「代入元と代入先が同じメモリーを参照します」と
読めるのですが、他に何か罠があるのでしょうか?

言葉で分からないのは「参照カウンタつきXX」の部分です。


[9932] Re:今更きけない 動的配列…(いや、まぁ聞くんだけどさ)返信 削除
2016/5/16 (月) 12:07:50 Mr.XRAY
▼ takiさん

> マスター 教えてください。

分かりません !! (キッパリ)

> Delphi/動的配列の罠
> http://tobysoft.net/wiki/index.php?Delphi%2F%C6%B0%C5%AA%C7%DB%CE%F3%A4%CE%E6%AB


あっ,これ,面白い !

>だから、「動的配列はポインタだ」という事だけ気をつけておけば
>いいのでしょうか?


だからか,どうかは分かりませんが (^^;
私的な立場では... ホホホッ.


[9942] 動的配列とポインタと型と...返信 削除
2016/5/16 (月) 18:19:38 Mr.XRAY
> >だから、「動的配列はポインタだ」という事だけ気をつけておけば
> >いいのでしょうか?
>
> だからか,どうかは分かりませんが (^^;
> 私的な立場では... ホホホッ.


誤解されると困るので,一応.
以下も動的配列といいますが,これは,代入できません.
([DCC エラー] Unit1.pas(64): E2008 互換性の無い型です) となります.

procedure TForm1.Button1Click(Sender: TObject);
var
  Array1 : array of Integer;
  Array2 : array of Integer;
begin
  // array1の確保と変更
  SetLength(Array1, 10);
  SetLength(Array2, 10);

  Array2 := Array1;  //これはエラー


この代入が可能なのは,type 節で定義した型やクラスのインスタンスです.
(コンポーネントもクラスです)
または,String 型や Integer 型のような単純な型 (?) の同じ型の変数同志です.
例えば,TIntegerDynArray は次のように定義されています.

type
  TIntegerDynArray = array of Integer;


ちょっ前のスレッドにありましたが,HQUERY もそうです.
HQUERY は Type で宣言されています.そのため,型が違うというエラーに
なったわけです.

type で前言した「型」は,実はポインタということですね.


[9946] Re:動的配列とポインタと型と...返信 削除
2016/5/16 (月) 20:07:16 taki
▼ Mr.XRAYさん

手続き(関数)の引数として動的配列を使うときに注意が必要という事みたいです。

type
  TTestAry = array of integer;

procedure ABC(buf:TTestAry);
begin
  Form1.Label1.Caption := inttostr(buf[0]);   // 999
  // 何の気なしに手続き内で値を変更する
  buf[0] := 888;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Abuf:TTestAry;
begin
  SetLength(Abuf,1);
  Abuf[0] := 999;
  // 手続きを呼び出す
  ABC(Abuf);
  // Abufの値が変化してしまう
  Label2.Caption := inttostr(Abuf[0]);   // 888
end;

これって
procedure ABC(var buf:TTestAry); と同じですよね。

『var』と書いていないのに var 扱いになる!!
踏んじゃいそうですね。



[9947] Re2:動的配列とポインタと型と...返信 削除
2016/5/16 (月) 21:09:32 Mr.XRAY
▼ takiさん

> これって
> procedure ABC(var buf:TTestAry); と同じですよね。
>
> 『var』と書いていないのに var 扱いになる!!
> 踏んじゃいそうですね。


う〜む.これはどう反応していいのか難しいです.悩みますです.
TList, TStringList 等,「型」の引数 (ポインタ) は全てそうですからね.

>   // Abufの値が変化してしまう

Abuf の値を変化させることができる.という見方もできますね (^^;


[9951] Re3:動的配列とポインタと型と...返信 削除
2016/5/16 (月) 22:50:45 taki
▼ Mr.XRAYさん

> う〜む.これはどう反応していいのか難しいです.悩みますです.
> TList, TStringList 等,「型」の引数 (ポインタ) は全てそうですからね.


http://mrxray.on.coocan.jp/Delphi/plSamples/780_FileInfoListETC.htm#04

サブフォルダ内を含めて全ファイル一覧を求めるプログラムにも
procedure GetFilesListAll(APath: String; FileList: TStringList);と
なってますね。

FileListに結果が入るのはそういう理由だったんですね。


[9953] Re4:動的配列とポインタと型と...返信 削除
2016/5/16 (月) 23:57:28 Mr.XRAY
▼ takiさん

> FileListに結果が入るのはそういう理由だったんですね。

です.
引数で結果を受け取ることができるわけです.
これもそうですが,
Delphi を使い始めた頃,先に書いた Type, クラス,クラスの継承,
本当にすごいことを考える人がいるもんだと感心したものです.

型の定義が面倒だと感じることがあるかも知れません.
でも,この型にうるさいのが,逆にいいこともあることは確かだと思います.

先の提示の TIntegerDynArray の件は,おそらく,単純型の Integer 等と
混合しているのではないかと...
私から言わせると「罠」どころか,明確に区別があり,便利だと思うぐらいです.
参照カウンタが問題なるのは,Windows API の関数を使う時ではないかと思います.

Delphi 特有の String 型の文字列は,参照カウンタを意識しないで使えます.
便利です.
この便利さに慣れてしまうと,Windows API で使用する null 終端文字列
との相互の代入に手間取ることになりますが (笑)


[▼次のスレッド]
INCM/CMT
Cyclamen v3.82