2010-03-09 172 views

回答

7
  1. 這些是兩個根本不同的構造。如果一個人比另一個更適合你的要求,那麼當然更喜歡它。數組[a,b,c]是一個三維的矩形數組。這意味着所有元素都存在,但取決於您的需求,可能人口稀少。數組[a] [b] [c]是三維鋸齒狀數組或陣列數組。我相信我曾經讀過一個資料來源(那時我認爲是權威的),鋸齒狀的數組通常比矩形數組更好。我不記得究竟是因爲某種與性能相關的原因(緩存?)還是其他原因。

+1

該來源可能是.NET框架設計指南或FXCop幫助文件。兩者都喜歡鋸齒狀的陣列。 – 2010-03-09 22:45:58

+1

有人可以解釋爲什麼參差不齊的數組可以比多維數組更快嗎? 恕我直言,多維數組應該更快,因爲計算存儲在此數組中的對象的確切地址要容易得多。 – 2010-03-09 22:49:31

+0

每個人都說鋸齒速度更快,但沒有人告訴我爲什麼:) – Poma 2010-03-09 23:18:18

0

如果你想要'矩形'數組,那麼數組[a,b,c]應該更快。
如果您需要其他形狀,那麼您應該使用Array [a] [b] [c] - 在這種情況下,第一行可以包含例如5個對象,第二個6個對象等等。

+0

一個鋸齒陣列[a] [b] [c]更快 – stmax 2010-03-09 23:10:20

1

鋸齒陣列(Array[a][b][c])速度稍快。它需要更多的代碼來創建。

6

矩形數組更容易初始化,但鋸齒形數組更快。鋸齒狀數組更快的原因是因爲存在直接支持一維數組的中間語言指令。比較遵循兩個反彙編:

C#的方法:

public static int A() 
{ 
    int[,] a = new int[5, 5]; 
    return a[3, 4]; 
} 

編譯爲:

.method public hidebysig static int32 A() cil managed 
{ 
    .maxstack 3 
    .locals init (
     [0] int32[0...,0...] a) 
    L_0000: ldc.i4.5 
    L_0001: ldc.i4.5 
    L_0002: newobj instance void int32[0...,0...]::.ctor(int32, int32) 
    L_0007: stloc.0 
    L_0008: ldloc.0 
    L_0009: ldc.i4.3 
    L_000a: ldc.i4.4 
    L_000b: call instance int32 int32[0...,0...]::Get(int32, int32) 
    L_0010: ret 
} 

和C#方法:

public static int B() 
{ 
    int[][] a = null; 
    return a[3][4]; 
} 

編譯爲:

.method public hidebysig static int32 B() cil managed 
{ 
    .maxstack 2 
    .locals init (
     [0] int32[][] a) 
    L_0000: ldnull 
    L_0001: stloc.0 
    L_0002: ldloc.0 
    L_0003: ldc.i4.3 
    L_0004: ldelem.ref 
    L_0005: ldc.i4.4 
    L_0006: ldelem.i4 
    L_0007: ret 
} 

,你可以看到的第一種方法使用(慢)方法調用來獲得一個數組項的值:

call instance int32 int32[0...,0...]::Get(int32, int32) 

而第二個使用(快得多)ldelem IL指令:

L_0004: ldelem.ref 
L_0005: ldc.i4.4 
L_0006: ldelem.i4 

這是使用VS2008在發佈模式下編譯的。基準測試顯示鋸齒陣列版本比矩形陣列版本快25%左右(使用順序以及隨機索引進行訪問)。

+0

謝謝,這是令人滿意的答案,但違反我的意願:) – 2010-03-10 13:34:13

+0

@henk:你能解釋在更詳細的鋸齒狀/矩形陣列情況下發生的/不發生的範圍檢查優化?我一直認爲加速是由於一維陣列的內置IL指令引起的...... – stmax 2010-03-10 20:29:49

相關問題