• Record 与 Class, Delphi有部分类改为记录了,他们是怎么释放的!


    记得我是在delphi2005里面看到Record可以和Class一样定义方法(Function、Procedure)的,最近几年不像年轻时太爱看语言新特性了。Delphi XE2将正则表达式加入到了系统,成为体系的一部分 System.RegularExpressions,但是它表现出来的是TRegEx记录,对,是记录,不是类,也许是为了效率考虑,之后也从没有看过实现,虽然我们大家都知道Delhpi是最大的开源软件(从1~现在26既 DX10.3所有的代码都是公开的)!

    最近想将一小片lazarus代码转回Delhpi,由于Lazarus系统自带正则表达式目前主推的是 RegExpr 类(很早就开源),将其转换到TRegEx记录,在实现上确实有改动较大举个列子,至少没有释放!

    function FindOutRex(const aString: string; const aRex: string): string;
    var
    {$IFDEF fpc}
      RegEx: TRegExpr;
    {$ELSE}
      RegEx: TRegEx;
      vM:TMatch;
    {$ENDIF}
    begin
      Result := ''; // 表示没有匹配的,Indicates that there is no match.
    {$IFDEF fpc}
      try
        RegEx := TRegExpr.Create;
        RegEx.Expression := aRex;
        if RegEx.Exec(aString) then
          Result := RegEx.Match[0];
      finally
        RegEx.Free;
      end;
    {$else}
      RegEx:=TRegEx.Create(aRex);
      vM:=RegEx.Match(aString);
      if vM.Success then
        Result := vM.Value;
    {$ENDIF}
    end;

    如果代码中大量使用正则表达式,由于一个是类一个是记录,一个存在建立、释放,一个只用形式上的建立也就是初始化,这这样更改量太大了。

    进一步跟踪发现Delphi在实现这个记录时其实用还是调用System.RegularExpressionsCore的类,也就是我们我们很早就用过的TPerlRegEx类,其实这个和lazarus里面就是一样一样的,类名现在稍有不同而已,好!现在关于这个项目中正则表达式类快速转换的问题可以很快解决了,我直接用继承类即可。

    但再看看Delphi代码你应该会想到,Delphi实现类的记录化,类是要实例化为对象,然后非接口的对象要可视化释放!这个在转化后的记录是怎么释放资源的呢!

    原来他是利用了”通告”,还是利用的接口特性——FNotifier: IInterface;!

    其代码定义在实现段

    TScopeExitNotifier = class(TInterfacedObject)
      private
        FRegEx: TPerlRegEx;
      public
        constructor Create(const ARegEx: TPerlRegEx);
        destructor Destroy; override;
        property RegEx: TPerlRegEx read FRegEx;
      end;
    ..
    // Helper to extract RegEx object
    function GetRegEx(const Notifier: IInterface): TPerlRegEx; inline;
    begin
      Result := TScopeExitNotifier(Notifier).RegEx;
    end;
    { TScopeExitNotifier}
    constructor TScopeExitNotifier.Create(const ARegEx: TPerlRegEx);
    begin
      FRegEx := ARegEx;
    end;
    
    destructor TScopeExitNotifier.Destroy;
    begin
      FRegEx.Free; // 在这里释放 ,This is where the release is
      inherited;
    end;
    ..
    { TRegEx }
    constructor TRegEx.Create(const Pattern: string; Options: TRegExOptions);
    begin
      FOptions := Options;
      FRegEx := TPerlRegEx.Create;
      FRegEx.Options := RegExOptionsToPCREOptions(FOptions);
      if (roNotEmpty in Options) then
        FRegEx.State := [preNotEmpty];
      FRegEx.RegEx := Pattern;
      FNotifier := TScopeExitNotifier.Create(FRegEx);
      if (roCompiled in FOptions) then
        FRegEx.Compile;
    end;

    那么在记录离开作用域将要释放的时候,FNotifier 自然会被nil,利用接口贴特性,这时正则表达类对象资源自然也就释放了。

  • 相关阅读:
    cnpm镜像安装
    wxParse解析html
    C++回调函数
    QT源码分析:QTcpServer
    QT实现支持加密的Sqlite数据库引擎
    VS2013+OpenCV3.4.2编译
    Android Tcp操作
    使用Delphi开发linux应用
    QT5.10+MinGW+OpenCV3.4.2编译
    C++ ActiveX开发的问题讨论
  • 原文地址:https://www.cnblogs.com/hieroly/p/12334223.html
Copyright © 2020-2023  润新知