[delphi] 스마트 포인터

2018-03-29

스마트 포인터

자동 객체 해제 클래스 테스트

  • 함수 안에서 제한적 사용

  • 개선 필요

코드 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

unit uSmartPointer;

interface

function DoSmartPointer( out Reference: TObject; Instance: TObject ): IUnknown;

implementation

type
TSmartPointer = class( TInterfacedObject )
private
FInstance: TObject;
public
constructor Create( AInstance: TObject );
destructor Destroy; override;
end;

{ TSmartPointer }

function DoSmartPointer( out Reference: TObject; Instance: TObject ): IUnknown;
begin
Result := TSmartPointer.Create( Instance );
TObject(Reference) := Instance;
end;

constructor TSmartPointer.Create(AInstance: TObject);
begin
FInstance := AInstance;
end;

destructor TSmartPointer.Destroy;
begin
FInstance.Free;

inherited;
end;

end.

1
2
3
4
5
procedure GetData;
var l: TList;
begin
DoSmartPointer( TObject(l), TList.Create )
end;

코드 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

unit SmartPointerClass;

interface

uses
Generics.Defaults;

type
TSmartPointer<T: class, constructor> = record
strict private
FValue: T;
FFreeTheValue: IInterface;
function GetValue: T;
private
type
TFreeTheValue = class (TInterfacedObject)
private
fObjectToFree: TObject;
public
constructor Create(anObjectToFree: TObject);
destructor Destroy; override;
end;
public
constructor Create(AValue: T); overload;
procedure Create; overload;
class operator Implicit(AValue: T): TSmartPointer<T>;
class operator Implicit(smart: TSmartPointer <T>): T;
property Value: T read GetValue;
end;

implementation

{ TSmartPointer<T> }

constructor TSmartPointer<T>.Create(AValue: T);
begin
FValue := AValue;
FFreeTheValue := TFreeTheValue.Create(FValue);
end;

procedure TSmartPointer<T>.Create;
begin
TSmartPointer<T>.Create (T.Create);
end;

function TSmartPointer<T>.GetValue: T;
begin
if not Assigned(FFreeTheValue) then
self := TSmartPointer<T>.Create (T.Create);
Result := FValue;
end;

class operator TSmartPointer<T>.Implicit(smart: TSmartPointer<T>): T;
begin
Result := Smart.Value;
end;

class operator TSmartPointer<T>.Implicit(AValue: T): TSmartPointer<T>;
begin
Result := TSmartPointer<T>.Create(AValue);
end;

{ TSmartPointer<T>.TFreeTheValue }

constructor TSmartPointer<T>.TFreeTheValue.Create(anObjectToFree: TObject);
begin
fObjectToFree := anObjectToFree;
end;

destructor TSmartPointer<T>.TFreeTheValue.Destroy;
begin
fObjectToFree.Free;
inherited;
end;


end.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

procedure TFormSmartPointers.btnImplicitCreateClick(Sender: TObject);
var
smartP: TSmartPointer<TStringList>;
begin
// smartP.Create;
smartP.Value.Add('foo');
Log ('Count: ' + IntToStr (smartP.Value.Count));
end;

procedure TFormSmartPointers.btnLeakClick(Sender: TObject);
var
sl: TStringList;
begin
// memory leak
sl := TStringList.Create;
sl.Add('foo');
Log ('Count: ' + IntToStr (sl.Count));
end;

procedure TFormSmartPointers.btnSmartClick(Sender: TObject);
var
sl: TStringList;
smartP: TSmartPointer<TStringList>;
begin
sl := TStringList.Create;
smartP := sl;
sl.Add('foo');
Log ('Count: ' + IntToStr (sl.Count));
end;

procedure TFormSmartPointers.btnSmartShortClick(Sender: TObject);
var
smartP: TSmartPointer<TStringList>;
begin
smartP := TStringList.Create;
smartP.Value.Add('foo');
TStringList(smartP).Add('foo2');
Log ('Count: ' + IntToStr (TStringList(smartP).Count));
end;

코드 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

unit ObjectGuardClass

integerface

type
IObjectGuard<T: class> = interface
function Value: T
end;

type
TObjectGuard<T: class> = class(TInterfacedObject, IObjectGuard<T>)
private
FValue: T;
public
constructor Create(Obj: T);
destructor Destroy; override;
function Value: T;
end;

type
TSmartPtr<T: class> = record
private
FGuard: IObjectGuard<T>;
public
class operator Explicit(const Obj: T): TSmartPtr<T>;
class operator Implicit(const Ptr: TSmartPtr<T>): T;
end;

implementation

{ SmartPtr<T> }

class operator TSmartPtr<T>.Explicit(const Obj: T): TSmartPtr<T>;
begin
Result.FGuard := TObjectGuard<T>.Create(Obj);
end;

class operator TSmartPtr<T>.Implicit(const Ptr: TSmartPtr<T>): T;
begin
if Ptr.FGuard <> nil then
Result := Ptr.FGuard.Value
else
Result := nil;
end;

{ TObjectGuard<T> }

constructor TObjectGuard<T>.Crete(Obj: T);
begin
FValue := Obj;
end;

destructor TObjectGuard<T>.Destory;
begin
FValue.Free;
inherited;
end;

function TObjectGuard<T>.Value: T;
begin
Result := FValue;
end;

end.

1
2
3
4
5
6
7
procedure TForm.btnSmartPtrClick(Sender: TObject);
var
SL: TStringList;
begin
SL := TSmartPtr<TStringList>(TStringList.Create());
SL.Add('Foo');
end;

참조