【问题标题】:Why does `Explicit(array of T)` receive garbage in Delphi 10? [duplicate]为什么 `Explicit(array of T)` 在 Delphi 10 中接收垃圾? [复制]
【发布时间】:2017-05-10 15:24:08
【问题描述】:

我正在使用 Delphi 10 Seattle。 当我编译这个单元时(它只是一个空白的 vcl 项目,带有一个注册了Button1Click 的按钮)它编译并运行,但数据不符合预期。函数Explicit(覆盖显式转换)将接收(6109508, -1, 3) 而不是(1, 2, 3)。为什么呢? 构造函数工作得很好,它具有相同的参数声明。

当我使用调试器查看data 时,它是(1, 2, 3),但是当我进入Explicit 并检查Values 时,它是(6109508, -1, 3)。当Values 不是const 时也是如此。

我使用TIntArray 只是为了表明这与TGeneric<integer> 具有相同的结果。

我错过了什么?或者这是一个错误?

unit Unit1;

interface
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
 TGeneric<T: record> = record
  private
    FData:  array of T;
  public
   class operator Explicit(const Values: array of T): TGeneric<T>;
   constructor Create(const Values: array of T);
 end;
   TIntArray = TGeneric<integer>;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

class operator TGeneric<T>.Explicit(const Values: array of T): TGeneric<T>;
begin
  Result :=  TGeneric<T>.Create(Values);
end;

constructor TGeneric<T>.Create(const Values: array of T);
begin
  SetLength(Self.FData, Length(Values));
   Move(Values[0], Self.FData[0], Length(Values) * SizeOf(T));
end;

procedure TForm1.Button1Click(Sender: TObject);
var a : TIntArray;
const data : array of integer = [ 1,2,3 ];
begin
  a := TGeneric<integer>.Create(data); // seems ok.
  a := TIntArray.Create(data); // seems ok.
  a := TGeneric<integer>(data); // sends garbage to Explicit.
  a := TIntArray(data); // sends garbage to Explicit.
end;

end.

【问题讨论】:

  • FWIW,如果T 是托管类型,TGeneric&lt;T&gt;.Create 将不起作用。例如,包含托管类型的记录。事实上,你自己的TGeneric&lt;T&gt; 就是这样的东西。
  • 位 T 是整数或任何其他“记录”。不管理记录。它们是价值观。
  • 我们必须升级到东京看看它是否已修复。我现在就关闭它。
  • 不是这样。如果记录包含托管类型,则记录是托管的。正如我所说,您的记录本身是受管理的。
  • 记录不受管理。它们是值:“记录是值类型,因此它们在赋值时被复制、按值传递并在堆栈上分配,除非它们被全局声明或使用 New 和 Dispose 函数显式分配。”没有什么可管理的。但是,在创建/处置时,该记录内使用的所有托管类型都会进行引用计数。这是题外话。

标签: delphi operator-overloading delphi-10-seattle


【解决方案1】:

此问题已在 another question 中提出,原为 reported 并已在 Delphi 10.2 中修复

【讨论】:

  • 我没有 Tokyo,但假设这是正确答案。
猜你喜欢
  • 2020-03-06
  • 1970-01-01
  • 1970-01-01
  • 2012-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-10
  • 1970-01-01
相关资源
最近更新 更多