2012-08-07 19 views
3

我有一個連續的緩衝區,帶有N個記錄,每個W字節寬。 N和W在編譯時是未知的。 N * M是500mb的訂單。我想在標準STL算法中使用它,例如sort()或nth_element()。我手邊有一個比較器。有沒有已經實施的方法可以這樣做?使用void *作爲STL中的固定寬度記錄

到目前爲止,我想通2種方式:

1)使用一個額外的載體,充滿指數0,...,N,排序它(使用替代數據的自定義比較),所以它類似於有序的數據記錄,然後按照該向量移動數據記錄。缺點:額外的內存,修復數據記錄順序的額外難度,這稍微不重要。

2)創建一些自定義迭代器(知道W),它將返回一些類似於記錄的臨時「虛擬」類實例,併爲該類重載swap(),以交換內存塊。缺點:有點棘手,有些脆弱(需要遵循一些STL內部知識,如知道swap()將被使用)。

+0

最後,我的解決方案如下:我確實創建了一個自定義迭代器,它返回「Proxy」類對象,其中包含指向該記錄的指針。我實現了swap(),並且我還實現了一個賦值構造函數/運算符。當swap()沒有被調用時,爲了擺脫賦值中的大量分配,我還實現了一個帶有原子鎖的單個靜態緩衝區(我確定在大多數情況下,1個緩衝區就足夠了)。當鎖定空閒時,使用預分配的緩衝區。當它忙時,內存像往常一樣分配。最後,在典型的使用情況下,swap()+單緩衝區減少到0。 – Codeguard 2012-08-22 11:55:08

回答

2

我會選擇第二種方法,但通過提供自定義複製語義,而不是自定義swap。使迭代器值類型成爲一個包含void*成員的類,並具有複製該成員指向的記錄的複製構造函數和賦值運算符。這不依賴於任何實現細節。

4

您的第二個選擇 - 編寫自定義迭代器 - 是一種可行的方法,並且工作得很好。

您不需要依賴swap正在使用:您只需重載代理對象的賦值運算符,該運算符在迭代器被解除引用時返回。 (注意在C++ 11中,需要使用「swap」元素的算法和函數來使用通過ADL找到的函數swap,但是仍然希望重載賦值運算符,儘管如此,尤其是如果您只是在移動數組時)

我不知道我頭頂上的一般實現,但作爲一個起點,您可以從我的一個庫(接近文件底部)看看stride_iterator, 。它包裝一個字節數組並覆蓋算術運算符,一次將迭代器移動N個字節,其中N僅在運行時纔可知。

+0

如果我不交換(),那麼將使用默認的交換,其中t = x,x = y,y = t。這樣,我還需要支持代理中的臨時存儲,這似乎涉及每個交換的額外的W字節分配,這是大量的分配。另一方面,如果我重寫swap(),我可以在沒有這些額外的分配的情況下交換記錄。 – Codeguard 2012-08-08 06:55:52

1

我會爲選項2)投票,但實際上並不需要爲存根類超載swap()。你只需要:

  • 創建了由迭代器
  • 實現用於分配的寬度的內存W¯¯
  • 一大塊落實拷貝構造函數,其分配塊的默認構造函數返回一個「存根」類的寬度爲W的內存,並複製內存的輸入塊。
  • 重載賦值運算符,以便將內存塊從一個實例複製到另一個實例。

這樣,swap()會自動適合您的班級。