動態陣列介紹----Delphi (轉)
動態陣列介紹----:namespace prefix = o ns = "urn:schemas--com::office" />
自從有了動態陣列,連結串列除了在教科書裡出現外,已經很少在實際中被使用了,事實也是如此,陣列的確比傳統連結串列快得多,而且也方便的多。
從 Delphi4起,開始了內建各種型別的動態陣列支援。但是,對我們來說動態陣列支援似乎做的不夠徹底,因為Delphi竟然連刪除、插入、移動連續元素的都沒有提供,讓人使用起來總覺得不夠爽!!! J 。作為一名員,我們當然要有自己解決問題的能力,下面就讓我們簡單介紹一下Delphi 下的動態陣列。
在Delphi中,陣列型別有靜態陣列(a : array[0..1024] of integer)、動態陣列(var a : array of integer)、指標陣列(即指向靜態陣列的指標)和開放陣列(僅用於引數傳遞)。靜態陣列、指標陣列有速度快的好處,動態陣列有大小可變的優勢,權衡之下就有了折衷的辦法,那就是定義的動態陣列在必要時轉換為指標。
動態陣列宣告之後,只有下面幾個函式可供操作:
1. 設定陣列大小,可以任意縮減或增加陣列大小
Procedure SetLength(var S ; NewLength : integer);
2. 取出連續元素,複製給另一個陣列變數
Function Copy(s;Index,Count : integer) : array ;
3. 取得陣列大小及上下限
Function Length(s):integer;
Function High(x):integer;
Function Low(x):integer;
值得注意的是,不加const或var修飾的動態陣列會被作為形參傳遞,而動態陣列用const修飾並不意味著你不能修改陣列裡的元素(不信你可以字自己在程式中試試。還有一點是High函式了Length 函式,所以我們在獲取陣列上限時最好直接用 Length(s) 函式。
動態陣列在空間中佔用4個位元組. 動態陣列在記憶體中的分配表如下:
偏移量 內容
-8 32-bit 引用計數
-4 32-bit 陣列長度
0..陣列長度 * (元素尺寸) - 1 陣列元素 元素尺寸=Sizeof(元素型別)
根據上面的分配情況,可以得到如下結果:
如果我們想要清空一個動態陣列只需要把“陣列長度”和“引用計數”清空即可。”引用上面的一句話就是:“權衡之下就有了折衷的辦法,那就是定義的動態陣列在必要時轉換為指標。”下面是清空動態陣列的函式:
procedure DynArraySetZero(var A);
var
P: PLongint; //佔用4個位元組,正好符合 32 位記憶體排列
begin
P := PLongint(A); // 指向 A 的地址
Dec(P); //P 地址偏移量是 sizeof(A),指向了陣列長度
P^ := 0; // 長度清空
Dec(P); // 指向引用計數
P^ := 0; //計數清空。
end;
上面的函式就這麼簡單,而且也非常高。
下面讓我們再來看看怎樣刪除動態陣列中的元素,函式體如下:
{************************************
A 變數型別 , elSize = SizeOf(A)
index 開始刪除的位置 ,Count 刪除的數量
****************************************}
procedure DynArrayDelete(var A; elSize: Longint; index, Count: Integer);
var
len, MaxDelete: Integer;
P : PLongint; //4 個位元組的長整形指標
begin
P := PLongint(A);// 取的 A 的地址
if P = nil then
Exit;
{
下面這句完全等同於 Dec(P) ; len := P^ 因為 Dec(P) = Pchar(P) – 4 同樣是移動4 位元組的偏移量,只不過後者按位元組來移動 }
len := PLongint(PChar(P) - 4)^; // 變數的長度 ,偏移量 -4
if index >= len then //要刪除的位置超出範圍,退出
Exit;
MaxDelete := len - index; // 最多刪除的數量
Count := Min(Count, MaxDelete); // 取得一個較小值
if Count = 0 then // 不要求刪除
Exit;
Dec(len, Count);// 移動到要刪除的位置
MoveMemory(PChar(P)+index*elSize , PChar(P)+(index + Count)*elSize , (len-index)*elSize); //移動記憶體
Dec(P); //移出 “陣列長度”位置
Dec(P); //移出“引用計數” 位置
//重新再分配調整記憶體,len 新的長度. Sizeof(Longint) * 2 = 2*Dec(P)
ReallocMem(P, len * elSize + Sizeof(Longint) * 2);
Inc(P); // 指向陣列長度
P^ := len; // new length
Inc(P); // 指向陣列元素,開始的位置
PLongint(A) := P;
end;
對上面的例子,我們需要注意的是 elSize 引數 ,它必須是 SizeOf(DyArray_Name),表示元素所佔用的位元組數。
相信看了上面的例子後,對於動態陣列的複製,移動想必也可以自己實現了吧 J
後續:
其實,Delphi 對許多型別的記憶體分配都很相似,比如 string 型別,其實它和動態陣列是很相似的,我們完全可以把它拿來當成動態陣列。實質上 string 是 Pchar 的簡易版本。不管怎麼說,瞭解一些記憶體的分配對我們這些開發人員來說還是有一些好處的。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-1008983/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java 語法介紹(四):陣列(轉)Java陣列
- Shell 陣列介紹陣列
- AWK 陣列介紹陣列
- 動態陣列陣列
- 全面介紹JavaScript陣列方法JavaScript陣列
- ES6 陣列介紹陣列
- 2-7 陣列:動態陣列陣列
- 建立動態陣列陣列
- 陣列004 動態建立一維陣列陣列
- 介紹 Go 的陣列和切片Go陣列
- javascript陣列操作簡單介紹JavaScript陣列
- 動態VLAN介紹
- List介面(動態陣列)陣列
- 介紹PostgreSQL的陣列型別FUSQL陣列型別
- javascript關聯陣列簡單介紹JavaScript陣列
- 簡單介紹最新python 字串陣列互轉問題Python字串陣列
- js將陣列轉換成CSV格式的方法簡單介紹JS陣列
- 簡單介紹Lua一維陣列與多維陣列的使用陣列
- 簡單介紹js 陣列 fill() 填充方法JS陣列
- Linux Awk 陣列操作詳細介紹Linux陣列
- Delphi COM程式設計介紹程式設計
- delphi中Treeview的使用介紹View
- 手動實現ArrayList動態陣列陣列
- DELPHI也可以實現控制元件陣列,用定義陣列變數實現控制元件陣列 (轉)控制元件陣列變數
- Mybatis介紹之 動態SQLMyBatisSQL
- C++動態建立二維陣列,二維陣列指標,以及動態二維陣列函式傳遞C++陣列指標函式
- 動態行轉列
- [JAVA] Java 陣列、多維陣列,動態、靜態初始化,陣列JVM記憶體模型分析Java陣列JVM記憶體模型
- 動態record陣列的應用陣列
- js--陣列的reduce()方法的使用介紹JS陣列
- js實現的陣列自定義排序介紹JS陣列排序
- NumPy 陣列切片及資料型別介紹陣列資料型別
- C++中的靜態聯編和動態聯編介紹(轉)C++
- Bootstrap Blazor 元件介紹 Table (一)自動生成列功能介紹bootBlazor元件
- 動態固定行轉列
- 演算法基礎:動態規劃陣列中滾動陣列的使用演算法動態規劃陣列
- shared_ptr和動態陣列陣列
- js宣告陣列的幾種方式簡單介紹JS陣列