追記 2023/12/17
DisposeOf についてで指摘していたとおり、Delphi 12 Athens で DisposeOf が deprecated になりました。
ARC廃止
Delphi 10.3 Rio のリリース時にコンパイラの ARC 対応を順次廃止するとアナウンスされました。
ARC廃止というのは重大な変更にもかかわらず、実は多くのユーザーが書いたコードには影響が少ないと思われます。
では、そもそも ARC とは何だったのでしょうか?
ARCとは
Automatic Reference Counting の頭文字をとったものです。
日本語では、自動参照カウント(方式のメモリ管理)と言われます。
例えば次のコードを ARC ありと ARC 無しで書いてみます。
procedure Foo;
var
Bar: TBar;
begin
Bar := TBar.Create;
Bar.Baz;
end; // スコープを抜けるとき自動的に削除
procedure Foo;
var
Bar: TBar;
begin
Bar := TBar.Create;
try
Bar.Baz;
finally
Bar.DisposeOf; // 自分で削除を指示
end;
end;
Delphi 3 の COM 対応で実装された自動参照カウント方式のメモリ管理にかなり近い物です。
ただ、違いは全てのオブジェクトが参照カウントで自動的に破棄されるという事です。
(他にも Weak 属性や RefCount プロパティなどいくつか違いがあります)
ただし、ARC 有りの環境だったとしても、ARC 無しのコード(自分で破棄を指示する)は有効です。
つまり、常に ARC 無しのコードのように書いていた場合は影響がありません!
DisposeOf について
DisposeOf は ARC の導入時に導入されたメソッドで、従来の Free に変わる物でした。
このメソッドは ARC の有り無しで挙動が異なります。
ARC | 実行される内容 |
---|---|
あり | 参照カウントの調査・破棄の指示 |
なし | Free を呼ぶ |
つまり、DisposeOf を使っておけば、ARC でも非 ARC でも正しい破棄手順になります。
Free と DisposeOf の違い
ARC 有効時の DisposeOf は破棄を「指示」するだけで実際のメモリ解放はしません。
一方 Free は呼び出すと直ぐにデストラクタを呼び出しメモリを解放します。
ARC 有効時の DisposeOf によって破棄を指示されたオブジェクトは、適切なタイミング(例えばメソッドから抜ける時)でメモリが解放されます。
影響を受けない書き方
Delphi ユーザーにおなじみの
A := TA.Create;
try
// なにか処理
finally
A.DisposeOf;
end;
try~finally~end
パターンを使って書いていれば ARC 廃止の影響は受けません!
とはいえ、将来 ARC 廃止時に DisposeOf が deprecated になる可能性はあります。
TInterfacedObject は心配無用
IInterface は、Delphi のインターフェースの基底インターフェースです。
このクラスが QueryInterface と、_AddRef, _Release を定義しています。
これらを実装したクラスが TInterfacedObject です。
TInterfacedObject (IInterface を実装したクラス)を使うと IInterface で導入された _AddRef, _Release をコンパイラが自動的に呼び出すコードを生成します。
そして、この機能は ARC の廃止に関係なく存続します。
Android や iOS の API は全てインターフェースで提供されていますが、基底クラスが TInterfacedObject を継承しているので、これからも特に問題無く動作します。
ARC 廃止で TInterfacedObject によるオブジェクトの管理も廃止されるのかと勘違いした人達がパニックに陥っていましたが、それはありません。
まとめ
言語機能根幹のドラスティックな変更になりますが、従来の try~finally~end
による破棄パターンを使っていれば、大きな影響は受けないでしょう。