Delphi 程式碼最佳化——字串篇 (轉)
關鍵詞:, AnisString, Pchar
freewizard
Delphi有三種字串型別:短字串(String[n],n=1..255)區為靜態分配,大小在編譯時確定,這是繼承於BP for Dos的型別;字元陣列(PChar)主要是為了相容各類,在BP7中已經出現,如今在Delphi中更加應用廣泛,其儲存區可以用字元陣列靜態分配,也可用GetMem手動分配;而長字串(AnsiString)是Delphi獨有的,其儲存區在執行時動態分配,最靈活也最易被濫用。
不重複初始化
Delphi預設字串型別AnsiString會自動初始化為空。如下程式碼:
var s:string;
begin
s:=';
……
end;
s:=';就屬多此一舉。但是值得注意的是這對返回值Result無效。而一般說來,用var實參傳遞比返回字串值要更快一些。
使用SetLength預分配長字串(AnsiString)
動態分配是AnsiString的一大長項,但容易弄巧成拙,一個典型的例子如下:
s2:=;
for i:=2 to length(s1) do s2:=s2+s1[i];
且不說可用Delete取代之,主要問題在於上例的迴圈中s2的記憶體區域被不停地重複分配,相當費時。一個簡單有效的辦法如下:
SetLength(s2,length(s1)-1);
for i:=2 to length(s1) do s2[i-1]:=s1[i];
這樣s2記憶體只會重新分配一次。
字串與動態陣列的執行緒(Thread Safety)
在Delphi 5以前動態陣列與長字串的操作這些非執行緒安全是由引用計數來處理其臨界問題的,而自Delphi5起就改為直接在一些臨界指令前加lock指令字首來避免這個問題。不幸的是這一修改的代價相當昂貴,因為在PentiumⅡ中lock指令相當費時,大概要耗費額外的28個指令週期來完成這一操作,因而整體至少下降一半。
解決這個問題的辦法只有一個,那就是修改Delphi RTL核心程式碼。在原後,將rtlsyssystem.pas中所有的lock替換為{lock},當然必須是整字替換。
如此還未完全,下一步是將Delphi4執行庫中也有的xchg指令去掉,因為該指令有隱含的lock字首,所以必須將system.pas內_LstrAsg和_StrLAsg兩個過程中的 XCHG EDX,[EAX] 替換為如下程式碼:
mov ecx,[eax]
mov [eax],edx
mov edx,ecx
OK大功告成,編譯一下,覆蓋system.dcu即可。如此其效率將比Delphi5提高6倍,比Delphi4提高2倍。
避免使用短字串
由於很多字串操作會先把短字串轉換為長字串,從而減慢了執行速度,因此還是少使用短字串為妙。
避免使用Copy函式
這也和濫用記憶體管理有關。一個典型的情形如下:
if Copy(s1,23,64)=Copy(s2,15,64) then ……
這樣導致分配了兩塊臨時記憶體,因而降低了效率。應當替換為如下程式碼:
i:=0;
f:=false;
repeat
f:=s1[i+23]<>s2[i+15];
inc(i);
until f or (I>63);
if not f then ……
同樣的,如下語句就顯得相當低效:
s:=Copy(s,1,length(s)-10);
應改為
Delete(s,length(s)-10,10);
順便提一句,在連線字串時,s:=s1+s2;簡單而有效;但在Delphi2下則s:=Format([%s%s],s1,s2);可能稍快些。
總是使用長字串,必要時轉換為Pchar
先看看AnsiString的定義:
type
Astring = packed record
allocSiz: Longint; //動態分配大小
refCnt: Longint; //引用計數
length: Longint; //實際長度
ChrArr:array[1..allocsiz-6]of char; //位元組序列
end;
其中Astring[1]將返回Astring.ChrArr[1]的內容。
很多人認為AnsiString是天生低效的。其實這在很大程度上是由程式碼編寫不良、記憶體管理亂用和缺乏支援的函式所致。如上所述,一旦被動態分配了一塊記憶體,長字串就成了一個線性的位元組序列,並無所謂的效率問題。當然,若有更多有效的函式支援那就更好了。
說到AnsiString到PChar的轉換,本質上有三個辦法:
(1) P:=@s[1];這會引發UniqueString呼叫。
(2) P:=PChar (s);這會先檢查s是否為空,若是,則返回nil,否則即返回s[1]的地址。
(3) P:=Pointer(s);這不會引發任何隱含呼叫,因而是在確定s非空情況下的最佳選擇。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-987732/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 從Delphi到Lazarus——Delphi轉換器
- 小程式字串轉成二維碼遇到的坑字串
- js字串string轉object物件 - 方法篇JS字串Object物件
- aardio教程五) 寫Python風格的aardio程式碼(字串篇)Python字串
- 程式碼隨想錄演算法訓練營第8天 | 字串 344.反轉字串 541. 反轉字串II 卡碼網:54.替換數字 151.翻轉字串裡的單詞 卡碼網:55.右旋轉字串演算法字串
- 中文字串 轉 unicode 編碼的字串字串Unicode
- 劍指offer—58_2.左旋轉字串—分析及程式碼(Java)字串Java
- Python程式碼閱讀(第41篇):矩陣轉置Python矩陣
- 151.翻轉字串裡的單詞 卡碼網:55.右旋轉字串字串
- Java程式碼實現帶時區時間字串轉為LocalDateTime物件Java字串LDA物件
- 08天【程式碼隨想錄演算法訓練營34期】第四章 字串part01(● 344.反轉字串 ● 541. 反轉字串II ● 卡碼網:54.替換數字 ● 151.翻轉字串裡的單詞 ● 卡碼網:55.右旋轉字串)演算法字串
- 程式碼隨想錄演算法訓練營第八天 | 字串:344反轉字串、演算法字串
- JAVA字串轉日期或日期轉字串Java字串
- JS json字串轉物件、物件轉字串JSON字串物件
- xml字串轉JSON字串XML字串JSON
- 程式碼最佳化記錄
- 科學計數法字串轉為對應的十進位制程式-C程式碼字串C程式
- delphi:string,PChar,Array of Char 之間的轉換
- 奇怪的字串最佳化字串
- c#動態執行字串指令碼(最佳化版)C#字串指令碼
- Java 正確的做字串編碼轉換Java字串編碼
- 萬能java字串編碼轉換工具類Java字串編碼
- Python 漢字區位碼、字串 相互轉換Python字串
- 效能最佳化 = 改改程式碼?
- 程式碼隨想錄演算法訓練營day8|344.反轉字串 ● 541. 反轉字串II ● 卡碼網:54.替換數字演算法字串
- 旋轉字串字串
- Java程式碼中字串拼接方式分析Java字串
- 程式碼隨想錄演算法訓練營,9月4日 | 344.反轉字串,541. 反轉字串II,卡碼網:54.替換數字演算法字串
- 控制程式碼表篇——程式控制程式碼表
- delphi opencvOpenCV
- 程式碼隨想錄演算法訓練營day09|151.翻轉字串裡的單詞,卡碼網:55.右旋轉字串,28.實現 strStr(),459.重複的子字串演算法字串
- c++ LeetCode (初級字串篇) 九道演算法例題程式碼詳解(二)C++LeetCode字串演算法
- 24個PHP程式碼最佳化技巧PHP
- Java學習之程式碼最佳化Java
- chatGPT幫我最佳化程式碼-2024.06.20ChatGPT
- 嵌入式程式碼最佳化技巧
- 第一個Spring程式(程式碼篇)Spring
- Python 萬能程式碼模版:爬蟲程式碼篇Python爬蟲
- 程式碼大全回顧篇...