考慮到下面的結構,宣告/使用它的動態陣列的最有效/正確的方法是什么:
typedef struct {
int a;
char b;
} Test;
方法一:
Test* tst = malloc(2 * sizeof *tst);
tst[0].a = 0;
tst[0].b = 1;
方法二:
Test **tst = malloc(2 * sizeof(Test*));
tst[0] = malloc(sizeof(Test));
tst[0]->a = 0;
tst[0]->b = 1;
uj5u.com熱心網友回復:
第一個,如果結構不是很大。現代 CPU討厭動態分配,您應該盡量避免“追逐指標”。
假設陣列的地址是 123456。當您訪問代碼的第一個版本中的元素時,CPU 請求記憶體芯片將地址 123456 處的資料告訴它,然后將其拇指旋轉一個小時(比喻地說)直到資料到來背部。它將一次獲得 64 個位元組(一個快取行),因此很可能一次獲得 8 個元素,它甚至可能提前請求接下來的64 個位元組(地址 123520)(這稱為預取)。因此,一旦您訪問第一個元素,您可以合理地猜測訪問接下來的幾個元素會很快,因為它們位于 CPU 快取中。
在代碼的第二個版本中,CPU 從地址 123456 請求 64 個位元組(可能還有下一個 64 個位元組),但它由 16 個指標組成。然后它必須查看這些指標并請求該地址的資料。如果指標說資料位于地址 654321,那么它必須請求地址 654321 并在另一個隱喻的小時內旋轉它的拇指。浪費時間!更糟糕的是,每個專案都是一個單獨的請求。下一個專案不會位于同一快取行中的地址 654329 - 它可能是一些完全不同的地址,編號 555555。因此您不會免費將其他專案放入快取中。
可以使用預取指令告訴 CPU 在處理第一個專案時獲取其他專案,但它永遠不會那么快。
現在,如果專案非常大,那么使用指標陣列可能會有意義。如果您的專案大于 256 位元組,那么它們將不適合同一快取行或(可能)預取的快取行,因此您不會通過將多個專案預加載到快取中來提高速度一次。通過將它們直接放入陣列中,您仍然不會丟失任何東西,所以您也可以這樣做。如果它們真的像 100kB 一樣大,那么浪費的記憶體量可能是個問題,那么您就有充分的理由使用指標。此外,如果您有不同大小的專案,那么您不能將它們直接放入陣列中(并非沒有大量作業),這也是使用指標的一個很好的理由。
請注意,您的示例結構非常小,并且在某些系統(64 位 Windows)上,它的大小無論如何都與指標相同。所以在指標所在的空間里,你還不如把結構!當然,并非所有結構都那么小。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/467401.html
標籤:C
上一篇:如何為二維陣列之一賦值?
下一篇:從檔案中讀取逗號分隔的單詞
