[英]C: Which is better? Malloc array of pointers to structures, or array of structures?
我一直對此感到好奇,當使用數組內部的結構時,就內存分配而言,為數組中的每個條目分配新結構是否更好,或者更好地分配足夠的空間在N個結構的數組中。
//pointer based:
struct myStructure ** tmp = malloc(sizeof(struct myStructure *) * N);
tmp[0] = malloc(sizeof(struct myStructure));
tmp[0]->whatever = true;
//or structure in the array:
struct myStructure * tmp = malloc(sizeof(struct myStructure) * N);
tmp[0].whatever = true
是否有任何好處超過一個或另一個? 我覺得使用第二種形式是更好的練習,因為你最終會減少較小的malloc調用,但可能會出現只能使用第一種方法的情況。
對此有何見解?
謝謝!
一般來說,我會使用第二種方式,因為,如果你使用所有的插槽,它:
malloc
/ free
(=>分配/解除分配更快更簡單); 另一方面,如果你不打算使用數組的所有插槽(但你必須能夠按需存儲許多struct
)並且你的struct
非常大,第一種方式可能很方便,所以保存內存是值得努力。 此外,如果您需要廉價地更改struct
的順序(盡管您也可以使用第二種方法通過使用分離的指針數組),這可能是值得的。
通常,第二個更好 [IMO] - 它可能會更便宜[內存和時間],並且肯定會更容易維護。
但是,在某些情況下, 第二種方法可能會失敗 - 當第一種方法成功時。 這可能是由於內存碎片造成的 - 所有結構都有足夠的內存,它只是不在你記憶中的“一個地方”。
目前有三個非常好的答案,為什么你應該使用第二種方法,所以我不會復制他們的答案。 我想說第一種方法有幾個好處:
根據系統中的實際需要,第一個陣列更容易增長和縮小 。 增加第一個指針數組非常簡單 - 每個元素總長度為4或8個字節,因此將數組大小加倍不會花費太多 。
第二個實際結構數組可能要大得多(通過sizeof struct foo
乘以元素數),如果realloc(3)
沒有足夠的可用空間,那么甚至可能會略微增長數組。
第一個數組使您能夠通過“句柄”引用系統中的對象,並根據需要重新排列其內存。 您可以在頁面大小的平板中分配底層對象,並將對象重新壓縮到幾乎完整的平板 - 允許您將頁面返回到操作系統以供以后使用。 系統中的其他對象必須通過另一個間接層來獲取引用的對象,但是當您移動對象時,那些客戶端對象(“指示對象”?)不需要更新其指針。
第一個數組中對象的生命周期是“解耦的” - 這些對象中的一些可能存在很長時間,而其他對象可能僅存活毫秒。 在第二個數組中,整個數組具有相同的生命周期。 您可以向第二個數組添加一個額外的數據結構來管理哪些對象是活動的,哪些是死的,或者在結構中添加新字段以指示哪些是活動的和死的,但這兩種方法都需要更多的工作。 對於第一個數組,如果指針是非NULL
,則該對象是實時的。
這兩種方法都有其優點。 為手頭的工作挑選合適的一個。
陣列中的結構通常更好; 你應該使用它,除非你有理由使用其他形式。
從代碼正確性的角度來看,你應該處理malloc()失敗。 如果循環中有1000個malloc(),則更有可能在錯誤處理代碼中出現編程錯誤。 同樣,如果您的數據結構更復雜,您更有可能泄漏某些東西。 所以單個malloc()更容易。
從分配速度的角度來看,malloc()顯然需要時間來運行,因此單個malloc()通常會更快。
從內存大小的角度來看,malloc()通常在每次分配時都會有一些開銷。 顯然,指針是一個額外的成本。 因此,如果分配1000個16字節結構,則最終可能會在malloc開銷中使用每個結構16個字節,並使用8個字節的指針,總計40,016個字節。 執行單個分配只需要8,016個字節。
從訪問速度的角度來看,單個陣列可能更快,特別是如果結構很小或者您按順序讀取結構。 如果結構很小,那么它們中的一些將適合單個高速緩存行,因此它們可以作為一組讀/寫。 如果按順序讀取結構,CPU可能會注意到對大數組的線性訪問並將其預加載到緩存中。 如果使用指針數組和單獨的分配,則內存布局更隨機,這些優化都不起作用。 此外,由於您正在訪問更多數據(指針),因此您的算法將更快地脫離數據緩存。
從內存碎片的角度來看,這取決於。 如果你有足夠大的結構(占你總RAM的很大一部分),那么你可能會遇到沒有足夠的連續空閑內存來分配一個大數組的情況,但是有足夠的分配一個指針數組和個人結構。 (例如,如果你的操作系統上的32位程序限制你的2GB內存,你的內存分配器已經分配了一半的內存,那么你不能做一個1.5GB的分配,但你可以做15 100MB分配)。 這種情況很少見,因為人們通常不會處理大數據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.