FreeBASIC マニュアルのトップに戻る

FreeBASIC ProPgObjectLifetime

目次→教本→プログラマーのための案内Dynamic Object and Data Lifetime←オリジナル・サイト

動的オブジェクトとデータの有効期間 左にメニュー・フレームが表示されていない場合は、ここをクリックして下さい

←リンク元に戻る プログラム開発関連に戻る

動的メモリ割り当ての宣言キーワードから作成された、Dynamic Object と、その Data有効期間

序文:

上記のように、動的に割り当てられた、このようなオブジェクトとデータの場合、オブジェクトの識別子変数の有効期間は、通常周囲のスコープと一致します(そうでない場合はこれよりも長くなる可能性があります)。 しかし、関連付けられたデータの有効期間は、関連付けられたデータの割り当て/割り当て解除はユーザー自身によってトリガーされるため、これと一致しません。

ユーザーによって静的な方法で割り当てられた、定義済みの擬似オブジェクトの場合
これらの事前定義された型変数(可変長文字列 (1) または可変長配列 (2))は、次のように静的な方法で割り当てられます(または同様の構文で):
(1) Dim [Shared] As String stringname ...
又は
(2) Dim [Shared] As datatype arrayname() ...
これらの変数は、2つのエンティティの集合なので、動的な擬似オブジェクト、と見なすことができます:
- 識別子変数(stringname (1), か arrayname() (2))に関連付けられた記述子、最初のエンティティ
- メモリ内の動的割り当て(文字列データ (1) または配列データ (2))を参照、2番目のエンティティ(名前なし)

記述子は、'Shared' が使用される場合は、.BSS または .DATA セクションに割り当てられ、そうでない場合は、プログラム・スタックに割り当てられます。
文字列データは、文字列の割り当てによって、ヒープ内で 割り当て/再割り当て/割り当て解除 され、それに応じて記述子も更新されます(空の文字列を割り当てても記述子は破棄されず、リセットされます)。
配列データは、'Redim' によって、ヒープ内で 割り当て/再割り当て され、'Erase' によって割り当て解除され、それに応じて記述子も更新されます('Erase' は記述子を破壊せず、再初期化します)。
そのため、このようなユーザーコマンドが適用されても、識別子変数は、スコープ内で常に定義されたままになり、メモリ割り当ては、この同じスコープ内で(ユーザー・コマンドに従って)動的に 変更/解放 できます。

ユーザーによって静的な方法で割り当てられた、動的オブジェクトの場合
ユーザーは、また、関連付けられた動的データを 割り当て/再割り当て/割り当て解除 するメンバー手続きを使って、複雑な UDT を介して、動的オブジェクトを定義できます。
これを実行するために通常使われるメンバー手続きは、コンストラクタ(割り当て用)、割り当て演算子(再割り当て用)、およびデストラクタ(割り当て解除用)です。

オブジェクト識別子変数が、静的な方法で割り当てられている場合(上記と同様):
Dim [Shared] As complexUDT instancename ...
識別子変数スコープに従って、オブジェクトデータの、自動割り当てと割り当て解除を誘導します(UDTコンストラクターとデストラクターへの暗黙的な呼び出しによる)。
2つの間で、動的データ割り当ては、ユーザーコマンドによって、大きく影響を受ける可能性があります(UDT用にオーバーロードされた演算子の明示的な呼び出しなど)。

単純な変数だが、ユーザーによって動的に割り当てられた場合
動的割り当てを宣言するために使われる、キーワード('Allocate', 'Reallocate', 'New', 'ImageCreate')は、有効期間が他のユーザーコマンド('Deallocate', 'Delete', 'ImageDestroy')に依存する、名前のないエンティティを作成します。
一般的に、これらの割り当てキーワードは、初期化 (1|3) または割り当て (2|4)、単純変数(ポインター (1|2)、または参照 (3|4))に使われる式に含まれます。 例:
(1) Dim As datatype Ptr DATApointername = New datatype ...
又は
(2) Dim [Shared] As datatype Ptr DATApointername
(2) .....
(2) DATApointername = New datatype ...
又は
(3) Dim Byref As datatype DATAreferencename = *New datatype ...
又は
(4) Dim [Shared] Byref As datatype DATAreferencename = *Cptr(datatype Ptr, 0)
(4) .....
(4) @DATAreferencename = New datatype ...

したがって、この場合、2つの異なるエンティティがあります:
- 名前付きポインター (1|2) または参照 (3|4)、最初のエンティティ、
- 割り当てられたメモリを、指す (1|2) または参照 (3|4) 、2番目のエンティティ(名前なし)。

2つのエンティティを混同しないでください。それぞれが独自の有効期間を持っています。
'Deallocate', 'Delete', 'ImageDestroy'、2番目のエンティティ(最初のエンティティではない)だけの割り当てを解除します。次をの用例を参照下さい:
(1|2) Delete DATApointername
又は
(3|4) Delete @DATAreferencename

ユーザーによって動的に割り当てられた動的オブジェクトの場合
動的オブジェクト(複雑な UDT)は、単純な変数(ポインター (1|2)、または参照 (3|4))を、初期化 (1|3) または割り当て (2|4) することにより、動的(上記と同様)に、割り当てることもできます。例として:

(1) Dim As complexUDT Ptr UDTpointername = New complexUDT ...
又は
(2) Dim [Shared] As complexUDT Ptr UDTpointername
(2) .....
(2) UDTpointername = New complexUDT ...
又は
(3) Dim Byref As complexUDT UDTreferencename = *New complexUDT ...
又は
(4) Dim [Shared] Byref As complexUDT UDTreferencename = *Cptr(complexUDT Ptr, 0)
(4) .....
(4) @UDTreferencename = New complexUDT ...

したがって、この最後のケースでは、3つのエンティティを考慮することができます:
- 名前付きポインター (1|2) または参照 (3|4)、最初のエンティティ、
- オブジェクトの割り当てられた項目を、指す (1|2) または参照する (3|4) 、2番目のエンティティ(名前なし)、
- 動的に割り当てられた関連データをアドレスする、3番目のエンティティ(名前なし)。

3つのエンティティを混同しないでください。それぞれが独自の存続期間を持っています。
'Delete' は、2番目のエンティティ(最初ではなく)の割り当てを解除し、これにより、最初に 3番目のエンティティの割り当てが解除されます。次をの用例を参照下さい:
(1|2) Delete UDTpointername
又は
(3|4) Delete @UDTreferencename

ユーザーによって動的に割り当てられた動的オブジェクト(複雑な UDT):
- 最初のエンティティ:UDT 参照、プログラム・スタックに、静的に割り当て
- 2番目のエンティティ:zstring ポインター項目(UDT 参照によって参照される)を持つ UDT インスタンス、ユーザーによって動的にヒープに割り当て
- 3番目のエンティティ:zstring データ(zstring ポインター項目によって参照される)。UDT 手続きメンバー(コンストラクタ、let 演算子、デストラクタ)によってヒープに動的に再割り当て

Type complexUDT
    Public:
        Declare Constructor ()
        Declare Constructor (ByVal p As ZString Ptr)
        Declare Operator Let (ByVal p As ZString Ptr)
        Declare Operator Cast () As String
        Declare Property info () As String ' allocation address, allocation size, string length
        Declare Destructor ()
    Private:
        Dim As ZString Ptr pz
End Type

Declare Sub prntInfo_printString (ByRef u As complexUDT)
 
 
Print "'Dim Byref As complexUDT ref = *New complexUDT(""Beginning"")':"
Dim ByRef As complexUDT ref = *New complexUDT("Beginning")
prntInfo_printString(ref)

Print "'ref = """"':"
ref = ""
prntInfo_printString(ref)

Print "'ref = ""FreeBASIC""':"
ref = "FreeBASIC"
prntInfo_printString(ref)

Print "'ref = ""Programmer's Guide / Declarations / Dynamic Object and Data Lifetime""':"
ref = "Programmer's Guide / Declarations / Dynamic Object and Data Lifetime"
prntInfo_printString(ref)

Print "'ref.Destructor()':"
ref.Destructor()
prntInfo_printString(ref)

Print "'ref.Constructor()':"
ref.Constructor()
prntInfo_printString(ref)

Print "'ref.Constructor(""End"")':"
ref.Constructor("End")
prntInfo_printString(ref)

Print "'Delete @ref':"
Delete @ref
@ref = 0 ' systematic safety to avoid double-delete on same allocation

Sleep


Constructor complexUDT ()
    Print "    complexUDT.Constructor()"
    This.pz = Reallocate(This.pz, 1)
    (*This.pz)[0] = 0
End Constructor

Constructor complexUDT (ByVal p As ZString Ptr)
    Print "    complexUDT.Constructor(Byval As Zstring Ptr)"
    This.pz = Reallocate(This.pz, Len(*p) + 1)
    *This.pz = *p
End Constructor

Operator complexUDT.Let (ByVal p As ZString Ptr)
    Print "    complexUDT.Let(Byval As Zstring Ptr)"
    This.pz = Reallocate(This.pz, Len(*p) + 1)
    *This.pz = *p
End Operator

Operator complexUDT.Cast () As String
    Return """" & *This.pz & """"
End Operator

Property complexUDT.info () As String
    Return "&h" & Hex(This.pz, SizeOf(Any Ptr) * 2) & ", " & _     ' allocation address
            Len(*This.pz) + Sgn(Cast(Integer, This.pz)) & ", " & _ ' allocation size
            Len(*This.pz)                                          ' string length
End Property

Destructor complexUDT ()
    Print "    complexUDT.Destructor()"
    This.pz = Reallocate(This.pz, 0)
End Destructor


Sub prntInfo_printString (ByRef u As complexUDT)
    Print "        " & u.info
    Print "        " & u
    Print
End Sub

出力:
'Dim Byref As complexUDT ref = *New complexUDT("Beginning")':
	complexUDT.Constructor(Byval As Zstring Ptr)
		&h001F2AD0, 10, 9
		"Beginning"

'ref = ""':
	complexUDT.Let(Byval As Zstring Ptr)
		&h001F2AD0, 1, 0
		""

'ref = "FreeBASIC"':
	complexUDT.Let(Byval As Zstring Ptr)
		&h001F2AD0, 10, 9
		"FreeBASIC"

'ref = "Programmer's Guide / Declarations / Dynamic Object and Data Lifetime"':
	complexUDT.Let(Byval As Zstring Ptr)
		&h001F2AD0, 69, 68
		"Programmer's Guide / Declarations / Dynamic Object and Data Lifetime"

'ref.Destructor()':
	complexUDT.Destructor()
		&h00000000, 0, 0
		""

'ref.Constructor()':
	complexUDT.Constructor()
		&h001F2AD0, 1, 0
		""

'ref.Constructor("End")':
	complexUDT.Constructor(Byval As Zstring Ptr)
		&h001F2AE0, 4, 3
		"End"

'Delete @ref':
	complexUDT.Destructor()

参照
プログラマーのための案内に戻る
←リンク元に戻る プログラム開発関連に戻る

ページ歴史:2019-09-01 23:57:27
日本語翻訳:WATANABE Makoto、原文著作者:fxm

ホームページのトップに戻る

表示-非営利-継承