TPoint 是 Delphi 中的原语吗?

Is TPoint a primitive in Delphi?

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

我查看了System.TypesTPoint的代码:

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。 有专家可以证实一下吗?

TPoint 不是 class。

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

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

编译器告诉我

"E2511 Type parameter 'T' must be a class type"

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

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

顺便说一下,TPoint 是在 System.Types 中定义的事实也可以回答我的问题“TPoint 是 Delphi 中的原语吗?”

TPoint 是一个记录。

值类型
Recordinteger 等基本类型是值类型。
这意味着它们是在堆栈上创建的。
当函数退出时,它会清理堆栈并通过这样做回收内存 space。

引用类型
这与作为引用类型的 classes 形成对比。
在堆上创建了一个 class,需要显式释放。

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

ARC
在 ARC 编译器(移动 + Linux)上,甚至 classes 也会使用引用计数自动管理。这意味着记录、classes 和托管类型之间的语义差异已被消除。

如果你愿意,你当然可以在堆上创建一条记录:

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

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

但是....方法?
现在记录有方法了。
然而,这只是语法糖。
您不能有 virtual/dynamic 方法,也不能有接口方法

下面两种方法完全等价:

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

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