IS TPoint是Delphi中的一个原语吗?

时间:2017-04-28 06:34:48

标签: delphi memory destructor primitive delphi-10-seattle

我在运行时创建了几个TPoint对象,但我没有销毁它们。

我查看了TPoint中的System.Types代码:

PPoint = ^TPoint;
  TPoint = record
    X: FixedInt;
    Y: FixedInt;
  public
    constructor Create(P : TPoint); overload;
    constructor Create(const X, Y : Integer); overload;

    //operator overloads
    class operator Equal(const Lhs, Rhs : TPoint) : Boolean;
    class operator NotEqual(const Lhs, Rhs : TPoint): Boolean;
    class operator Add(const Lhs, Rhs : TPoint): TPoint;
    class operator Subtract(const Lhs, Rhs : TPoint): TPoint;

    class operator Implicit(Value: TSmallPoint): TPoint;
    class operator Explicit(Value: TPoint): TSmallPoint;

    class function PointInCircle(const Point, Center: TPoint; const Radius: Integer): Boolean; static; inline;
    /// <summary> Zero point having values of (0, 0). </summary>
    class function Zero: TPoint; inline; static;

    function Distance(const P2 : TPoint) : Double;

    procedure SetLocation(const X, Y : Integer); overload;
    procedure SetLocation(const P : TPoint); overload;
    procedure Offset(const DX, DY : Integer); overload;
    procedure Offset(const Point: TPoint); overload;
    function Add(const Point: TPoint): TPoint;
    function Subtract(const Point: TPoint): TPoint;
    function IsZero : Boolean;

    function Angle(const APoint: TPoint): Single;
  end;

通过阅读它,我看到没有destructor,而且它是原始记录。 我不会在某一点上掌握Delphi以确定它,但我认为不需要调用MyPoint.Free。 有些专家可以证实吗?

2 个答案:

答案 0 :(得分:4)

TPoint是一张唱片。

值类型
Recordinteger等基本类型是值类型 这意味着它们是在堆栈上创建的 当函数退出时,它会清理堆栈,这样就可以回收内存空间。

参考类型
这与作为参考类型的类形成对比 在堆上创建一个类,需要显式释放。

托管类型
正好处于这两个极端之间managed types,如stringinterface 这些是在堆上创建的,但编译器使用编译器魔术在引用计数降至零时自动销毁它们。 因为这个托管类型据说有value sementics

<强> ARC
在ARC编译器(移动设备+ Linux)上,甚至可以使用引用计数来自动管理类。这意味着记录,类和托管类型之间的语义差异已被消除。

如果需要,您当然可以在堆上创建记录:

type
  PRecord = ^TMyRecord;
var
  HeapRec: PRecord;
begin
  GetMem(HeapRec, SizeOf(TMyRecord));
  try
    do stuff with HeapRec........
  finally
   FreeMem(HeapRec);

请记住始终将记录作为const参数传递(如果可能)。否则编译器将浪费时间制作记录的副本。

但....方法?
记录现在有方法。
然而,这仅仅是语法糖 您不能拥有虚拟/动态方法,也不能使用接口方法

以下两种方法完全等效:

//Pre Delphi 2006
function CloneTMyRecord(const Self: TMyRecord): TMyRecord;

//Post Delphi 2006
function TMyRecord.Clone: TMyRecord;

答案 1 :(得分:0)

我本可以删除这个问题,但由于我有疑问,所以对其他人有用。

TPoint不是一个班级。

让我信服的是,我试图做一个像这样定义的对象列表:

uses Generics.Collections;
//
PointsList: TObjectList<TPoint>;

并且编译器告诉我

  

“E2511类型参数'T'必须是类类型”

所以这让我确信TPoint不是一个对象,因此不能被释放。 此外,关于将TPoint存储在List中,该线程描述了使用TListstore array of TPoint inside TObjectList更好地使用泛型。事实上,TPoint列表已安全地定义为TList<TPoint>

此外,我尝试使用Eurekalog搜索泄漏,并且未释放的TPoint不会像未释放的TStringList那样泄漏。

顺便说一下,在TPoint中定义System.Types的事实应该回复我的问题/主题标题“我在Delphi中找到一个原语吗?”