广汉三星堆 發表於 2020-6-17 13:10:00

说说Delphi 10.4的对象释放

<p>随着Delphi 10.4去掉了ARC,统一移动平台与桌面平台的内存管理,那对于释放对象,有什么变化呢?</p>
<p>先看看10.4的代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TObject.Free;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> under ARC, this method isn't actually called since the compiler translates</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> the call to be a mere nil assignment to the instance variable, which then calls _InstClear</span><span style="color: rgba(0, 128, 0, 1)">
{</span><span style="color: rgba(0, 128, 0, 1)">$IFNDEF AUTOREFCOUNT</span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> Self &lt;&gt; <span style="color: rgba(0, 0, 255, 1)">nil</span> <span style="color: rgba(0, 0, 255, 1)">then</span>
    <span style="color: rgba(0, 0, 255, 1)">Destroy</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$ENDIF</span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TObject.DisposeOf;
</span><span style="color: rgba(0, 0, 255, 1)">type</span><span style="color: rgba(0, 0, 0, 1)">
TDestructorProc </span>= <span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> (Instance: Pointer; OuterMost: ShortInt);
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$IFDEF AUTOREFCOUNT</span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> Self &lt;&gt; <span style="color: rgba(0, 0, 255, 1)">nil</span> <span style="color: rgba(0, 0, 255, 1)">then</span>
<span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
    Self.__ObjAddRef; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Ensure the instance remains alive throughout the disposal process</span>
    <span style="color: rgba(0, 0, 255, 1)">try</span>
      <span style="color: rgba(0, 0, 255, 1)">if</span> __SetDisposed(Self) <span style="color: rgba(0, 0, 255, 1)">then</span>
      <span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
      _BeforeDestruction(Self, </span><span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">);
      TDestructorProc(PPointer(PByte(PPointer(Self)^) </span>+ vmtDestroy)^)(Self, <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
      </span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)">
      Self.__ObjRelease; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> This will deallocate the instance if the above process cleared all other references.</span>
    <span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$ELSE</span><span style="color: rgba(0, 128, 0, 1)">}</span><span style="color: rgba(0, 0, 0, 1)">
Free;
</span><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$ENDIF</span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p>可以清楚的看到,在DisposeOf中,如果没有定义<span style="color: rgba(0, 128, 0, 1)">AUTOREFCOUNT</span>编译变量,则直接调用Free方法。由于去掉ARC,<span style="color: rgba(0, 128, 0, 1)">AUTOREFCOUNT</span>不再定义,所以调用DisposeOf,就是调用Free。现在可以忘记DisposeOf了,<strong>所有平台释放对象,就用Free。</strong></p>
<p>接下来,再看看FreeAndNil方法:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">procedure</span> <span style="color: rgba(0, 0, 255, 1)">FreeAndNil</span>(<span style="color: rgba(0, 0, 255, 1)">const</span><span style="color: rgba(0, 0, 0, 1)"> Obj: TObject);
</span><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$IF not Defined(AUTOREFCOUNT)</span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
Temp: TObject;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Temp :</span>=<span style="color: rgba(0, 0, 0, 1)"> Obj;
TObject(Pointer(@Obj)^) :</span>= <span style="color: rgba(0, 0, 255, 1)">nil</span><span style="color: rgba(0, 0, 0, 1)">;
Temp.Free;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$ELSE</span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Obj :</span>= <span style="color: rgba(0, 0, 255, 1)">nil</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$ENDIF</span><span style="color: rgba(0, 128, 0, 1)">}</span></pre>
</div>
<p>这个方法,同样使用了<span style="color: rgba(0, 128, 0, 1)">AUTOREFCOUNT</span>编译变量。</p>
<p>为了验证移动平台下,是否定义了<span style="color: rgba(0, 128, 0, 1)">AUTOREFCOUNT</span>,笔者做了个测试代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TForm1.FormCreate(Sender: TObject);
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$IFDEF AUTOREFCOUNT</span><span style="color: rgba(0, 128, 0, 1)">}</span><span style="color: rgba(0, 0, 0, 1)">
   Text1.Text:</span>=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">AUTOREFCOUNT</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$ELSE</span><span style="color: rgba(0, 128, 0, 1)">}</span><span style="color: rgba(0, 0, 0, 1)">
   Text1.Text:</span>=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Not Defined AUTOREFCOUNT</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$ENDIF</span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p>事实证明,在android运行时,显示<span style="color: rgba(128, 0, 0, 1)">Not Defined AUTOREFCOUNT</span>。没有定义<span style="color: rgba(0, 128, 0, 1)">AUTOREFCOUNT</span>,你可按这个去读上面的代码了!</p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/kinglandsoft/p/13151911.html
頁: [1]
查看完整版本: 说说Delphi 10.4的对象释放