在從C ++到Delphi的移植代碼的過程中,通常必須使用STL集合來輸入代碼。德爾菲提供的一組收藏非常苦風,因此有時
很難找到合適的替代品。有時,您會遇到對象放置在堆棧中或使用其自己的內存分配器的代碼。
我真的不喜歡建議的數據刷新模式。要更新數據,我需要從集合中檢索其中的值,更新值,然後將更改的值重新放回。這需要至少兩個額外的副本操作。我們不能將數據項作為VAR參數傳遞給過程。
集合無法更改內存的分配方式。對象和記錄的內存是從一個共享堆中分配的。使用後,必須小心地將內存返回堆。正確釋放內存並不總是一項瑣碎的任務,而且處理器的時間和編程編寫此代碼的時間都需要時間。在STL中,您可以為各種收藏集指定自己的內存分配器。
該實施依賴於記錄和指針。到目前為止,我認為沒有辦法使用標準對象實現我想要的東西。對象的創建和破壞使用共享的內存堆。無法將對象放在呼叫堆棧上。不支持舊的舊“對象”,並不支持為此類型的添加新功能。
該集合實現依賴於基於類型內存區域的機制內存管理。使用鍵入的內存區域可以簡化許多任務的解決方案:
釋放內存的任務變得更加容易,並且可以更快地完成。
眾所周知,標準內存管理器必須是線程安全的事實。只有一個線程可以在任何給定時間訪問內存管理器。分配和釋放存儲器使用相互排除機制,這不是一個快速的操作,尤其是在內存大量碎片片上。使用單獨的鍵入內存區域時,我們僅在增加所需內存並在使用後刪除結構時才參考標準內存管理器。
支持具有指定內存分配器的能力的基本結構。列表的元素通過指針訪問。通常,值的內存位於所謂的分段內存區域中,在操作過程中不會移動。如果有必要增加區域的內存,則將為其分配附加的內存段。這意味著我們可以通過指針訪問該區域中的數據項。
對於數組,我們使用所謂的連續內存區域。通過索引訪問數據項。如有必要,增加區域的內存,為其分配了大尺寸的段,並將來自當前存儲器段的數據複製到新段。複製數據後,將刪除舊段。
最終,通過指針進行工作非常方便。代碼變得更簡單,更簡潔。但是,如果您沒有指針的經驗,則很容易“射擊自己”。對於封裝的粉絲,您可以將所需的結構匯總為私人領域。接下來,我們僅通過覆蓋公共部分中所需的方法和屬性來打開接口的必要部分。如果我們放入內聯選項,我們會避免額外的費用。 Delphi編譯器將不會為覆蓋方法生成代碼。在方法調用的位置,將直接調用聚合結構方法。
TsgTuple<T1, ...>通用元素TsgArray<T>通用數組,帶有來自共享內存區域的內存分配TsgList<T>通用值列表TsgRecordList<T>指針訪問的值的通用列表TsgLinkedList<T>通用雙向鏈接列表TsgForwardList<T>通用單向鏈接列表TsgHashMap<Key, T>通用無序詞典TsgMap<Key, T>基於2-3棵樹的通用有序詞典TsgSet<Key>基於2-3棵樹的通用集TsgPointerArray未型指針清單TsgPointerList未型的指針訪問的值列表TCustomLinkedList未型雙向鏈接列表TsgCustomTree棵樹我們已經開始添加Delphi迭代器。現在,我們可以for p in List do;最有趣的是,我們使用記錄來實現迭代器,並且它有效!與使用對象相比,生成的代碼效率更高,而且很不錯,沒有對堆的調用,迭代器的變量位於堆棧上。事實證明,這對我來說是一個令人驚喜的驚喜!
指定內存分配器的能力也意味著我們主要與記錄一起工作。通常,某些結構使用一個或多個內存區域,這是一個簡單的內存管理器。使用結構後,我們有機會通過釋放內存區域來返回所有佔用的內存。我們使用繼承有局限性。在某些情況下,我們可以用聚合和助手代替繼承。通常用於實施集合,這不是問題。使用記錄可以堆疊收集。有時這很方便。
對像池允許您在創建對像是內存密集型或創建有限數量的某個類型對象時管理結構的重複使用。
如果我們停止使用某些東西,那麼並不總是值得刪除結構或對象。通常,必須重新創建對象。