加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 使用默认排序将TList> 64位与32位排序

发布时间:2020-12-15 04:06:44 所属栏目:大数据 来源:网络整理
导读:在32位与64位下编译时,TPair的默认排序似乎存在差异.在32位下,默认排序的行为类似于在对的Key上排序,在64位下,它看起来按值排序.这是预期的,还是我错过了什么? 使用Delphi XE2进行测试,更新4.在VCL应用程序中,将按钮,复选框和列表框拖放到屏幕上,声明以下类
在32位与64位下编译时,TPair的默认排序似乎存在差异.在32位下,默认排序的行为类似于在对的Key上排序,在64位下,它看起来按值排序.这是预期的,还是我错过了什么?

使用Delphi XE2进行测试,更新4.在VCL应用程序中,将按钮,复选框和列表框拖放到屏幕上,声明以下类型

type TPairComparer = TComparer<TPair<integer,integer>>;

然后将下面的代码放在OnClick按钮上并运行.在32位下,使用默认排序,按键列出对,即1,2,3,4,5,6.在64位下,这些对按值列出,即2,6,7,8,9,而不是按键.

为了使代码在两个平台上一致地工作,我需要指定我自己的比较器来强制在64位可执行文件上按键排序.

procedure TForm1.Button1Click(Sender: TObject);
 var PriorityList           : TList<TPair<Integer,integer>>;
     Pair                   : TPair<integer,integer>;
     PairComparer           : IComparer<TPair<integer,integer>>;
     iLoop                  : integer;
 begin

 PriorityList := TList<TPair<Integer,integer>>.Create;

 PairComparer := TPairComparer.Construct(
 function(const Left,Right: TPair<integer,integer>): Integer
 begin
      case Left.Key = Right.Key of
           true : Result := 0;
      else        case Left.Key < Right.Key of
                       true : Result := -1;
                  else        Result := +1;
                  end;
      end;
 end);

 Pair.Key   := 6;
 Pair.Value := 6;
 PriorityList.Add(Pair);

 Pair.Key   := 5;
 Pair.Value := 5;
 PriorityList.Add(Pair);

 Pair.Key   := 4;
 Pair.Value := 8;
 PriorityList.Add(Pair);

 Pair.Key   := 3;
 Pair.Value := 9;
 PriorityList.Add(Pair);

 Pair.Key   := 2;
 Pair.Value := 7;
 PriorityList.Add(Pair);

 Pair.Key   := 1;
 Pair.Value := 2;
 PriorityList.Add(Pair);

 case Checkbox1.Checked of
      true  : PriorityList.Sort;
      false : PriorityList.Sort(PairComparer);
 end;

 ListBox1.Clear;
 for iLoop :=  0 to PriorityList.Count-1 do
     ListBox1.Items.Add(Format('Key : %d,Value : %d',[PriorityList[iLoop].Key,PriorityList[iLoop].Value]));

结束;

解决方法

这种类型的默认比较器非常随意.编译器不使用任何记录组成的知识.您当然没有告诉它您希望哪个成员成为主要的排序键.所以它可以自由地做它想要的东西.

在32位中,8字节记录的默认比较器是通过调用类似CompareMem的函数实现的.因此,字节按递增的地址顺序进行比较.因此关键更重要.

在64位下,默认比较器将类型视为无符号64位整数,因此字节按递减的地址顺序进行比较,这是小端.因此价值更重要.

相关代码位于Generics.Defaults的实现部分:

function Comparer_Selector_Binary(info: PTypeInfo; size: Integer): Pointer;
begin
  case size of
    // NOTE: Little-endianness may cause counterintuitive results,// but the results will at least be consistent.
    1: Result := @Comparer_Instance_U1;
    2: Result := @Comparer_Instance_U2;
    4: Result := @Comparer_Instance_U4;
    {$IFDEF CPUX64}
    // 64-bit will pass const args in registers
    8: Result := @Comparer_Instance_U8;
    {$ENDIF}
  else
    Result := MakeInstance(@Comparer_Vtable_Binary,size);
  end;
end;

最重要的是,只要您希望对记录进行排序,就需要提供真正的比较器.只有内置数字和字符串类型才有明确定义的有序比较器.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读