【发布时间】:2015-03-31 20:43:12
【问题描述】:
我是 Delphi 的新手,具有 C++ 背景,并试图弄清楚如何实现智能指针。我遇到了以下帖子,我试图将其用作我自己的起点:Delphi - smart pointers and generics TList
但是我无法使用 Delphi XE7 编译之前的代码(编译器错误在代码中显示为 cmets)。另外,如果有人真正解释了代码的逻辑,我将不胜感激(最初我想将该类用作实用程序类的一个下降,但现在我想了解实际发生的情况)。我隐约明白,因为智能指针实现是从 TInterfacedObject 继承的,所以它是引用计数的,但除此之外的任何东西对我来说都没有意义:)
unit SmartPointer;
interface
uses
SysUtils, System.Generics.Collections;
type
ISmartPointer<T> = reference to function: T;
// complains ISmartPointer<T> expecting an interface type
TSmartPointer<T: class, constructor> = class(TInterfacedObject,ISmartPointer<T>)
private
FValue: T;
public
constructor Create; overload;
constructor Create(AValue: T); overload;
destructor Destroy; override;
function Invoke: T;
end;
implementation
{ TSmartPointer<T> }
constructor TSmartPointer<T>.Create;
begin
inherited;
FValue := T.Create;
end;
// complains: overload procedure TSmartPointer.Create must be marked with the overload directive
constructor TSmartPointer<T>.Create(AValue: T);
begin
inherited Create;
if AValue = nil then
FValue := T.Create
else
FValue := AValue;
end;
destructor TSmartPointer<T>.Destroy;
begin
FValue.Free;
inherited;
end;
function TSmartPointer<T>.Invoke: T;
begin
Result := FValue;
end;
end.
尝试将先前的智能指针与以下测试代码一起使用,导致编译器错误……我错过了什么?
program TestSmartPointer;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, SmartPointer;
type
TPerson = class
private
_name : string;
_age : integer;
public
property Name: string read _name write _name;
property Age: integer read _age write _age;
end;
var
pperson : TSmartPointer<TPerson>;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
pperson := TSmartPointer<TPerson>.Create();
// error on next line: undeclared Identifier: Name
pperson.Name := 'John Doe';
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
【问题讨论】:
-
我的建议是不要使用智能指针。它们是不适合该语言的成语。
-
关于顺序,在 C++ RAII 中,您知道当对象超出范围时,所有资源都会被清理,以相反的获取顺序。您不知道这些 Delphi“智能”指针会发生什么顺序。您所知道的是,它发生在过程返回时。范围不能小于过程。而且你无法控制顺序。如果这是个好主意,那么每个人都会这样做。
-
智能指针是死胡同。使用 try/finally 处理对象的生命周期是简单且可预测的。如果您犯了错误,FastMM 可以帮助您立即找到泄漏点。 RTL 有很多问题,但是手动处理对象造成的内存泄漏并不是这里的大问题。 (移动 ARC 模型是另一种球类游戏,在当前状态下,存在大量错误和混乱)。
-
@DavidHeffernan 您可以拥有比过程更小的可预测顺序和范围。您所要做的就是将智能指针设为 nil,它会在此时触发析构函数(当然,如果您对智能指针实例的引用不超过一个)。
-
我认为在 Delphi 中使用智能指针没有任何问题。它们没有什么不适合 Delphi 语言的。如果引用计数对象实例合适,那么智能指针也合适。
标签: delphi smart-pointers delphi-xe7