[英]Which C++ stl container should I use?
想象一下以下要求:
測量數據應該記錄下來,用戶應該能夠遍歷數據。
uint32_t timestamp;
uint16_t place;
struct SomeData someData;
在結構中具有時間戳記( uint32_t
),位置( uint16_t
)和一些數據
具有恆定數量的數據集。 如果有新的,最舊的被扔掉。
“位置”的數量是動態的,用戶可以在運行時插入新的
只有在位置相同的情況下,才有可能遍歷數據到下一個新的或更舊的數據集
只需要在最后插入
程序啟動時應分配一次內存
插入不必太快,但不應長時間阻塞其他線程,這可能會遍歷容器
內存需求應該低
編輯:-容器應該所有否則不使用的內存,因此它可能很大。
我不確定應該使用哪個容器。 這是一個嵌入式系統,不應使用boost等。
我看到以下可能性:
std :: vector-缺點:最后插入要求復制所有對象,在此期間,另一個線程無法訪問該向量。 編輯:這可以通過將其實現為循環緩沖區來避免-參見下面的注釋。 當遍歷向量時,我必須測試地點ID。 將大量內存分配為一個塊也許也可能是一個問題-因為內存可以分段?
std::deque
pop_back
與std::vector
插入(和pop_back
)相比更快,但是需要內存嗎? 如果插入在末尾,則迭代器不會變得無效。 但是我仍然必須迭代並測試第二個ID(“位置”)。 我認為不需要像矢量或數組那樣在一個大塊中分配所有內存。 如果在前面添加一個元素,然后在末尾刪除另一個元素(或先刪除然后添加),我猜是否沒有發生內存分配?
std::queue
我應該使用隊列而不是雙端隊列? 在許多實現中,是否確實像隊列隊列那樣冒充了隊列管理員?
std::map
map-像雙端隊列一樣,現有元素的任何迭代器都不會失效。 如果我將鍵組合為位置和時間戳,那么遍歷地圖的迭代速度可能會更快,因為它已經排序了? 一張圖的內存要求?
std::multimap
由於位數不是恆定的,因此我無法使用“ place”作為索引來制作多重地圖。
std::list
list-在這里比雙端隊列沒有優勢嗎?
有些人建議使用循環緩沖區。 如果我不希望將內存分配為一個大塊,我仍然必須使用容器,並且上面的大多數問題仍然有效。
更新:我將使用此處建議的環形緩沖區,但使用雙端隊列作為基礎容器。 為了能夠快速滾動帶有預選“位置”的數據集,我最終將在數據結構中引入兩個附加索引,這些索引將指向具有相同位置的上一個和下一個索引。
將使用多少內存? 在我的特殊情況下,該結構的大小為56個字節。 gnu lib使用512字節作為最小塊大小,IAR編譯器使用16字節。 因此,使用的塊大小將分別為512或56個字節。 除了兩個迭代器(每個使用4個指針)和大小外,每個塊還將存儲一個指針。 因此,與使用std :: vector或數組相比,在iar編譯器(塊大小為56字節)的實現中,開銷(在32位系統上)為7%。 在gcc實現中,將在塊中容納9個對象(504字節),而每個塊需要512 + 4字節,這增加了2%。
塊大小不大,但是指針數組所需的連續內存大小已經相當大,尤其是對於一個塊是一個結構的實現。
一個std :: list每個結構將需要2個指針,在我的情況下,在32位系統上,這是14%的開銷。
...內存可以分段嗎?
不, std::vector
分配連續的內存,如該鏈接中所述。 數組也是連續的,但是您也可以使用向量。
std::deque
是分段的,您說過不需要。 還是要避免分配單個大塊? 還不清楚
無論如何,如果您真的想要一個圓形緩沖區,它比矢量沒有任何好處(因為無論如何您永遠都不會從前/后添加/刪除元素),並且您無法控制塊的大小。
...在許多實現中,隊列是否像雙端隊列一樣被設置為真的嗎?
是的,這是所有實現中的默認設置。 請參閱鏈接的文檔或任何體面的書。
聽起來好像不想要FIFO隊列,所以我不知道您為什么要考慮這個隊列-接口不符合您的要求。
...通過地圖迭代可能更快,因為它已經排序了?
在大多數現代服務器/桌面體系結構上,映射會較慢,因為推進迭代器會涉及指針追逐(這會影響流水線操作)和可能的緩存未命中。 您的匿名嵌入式體系結構可能對這些影響不太敏感,因此映射可能對您來說更快。
...一張地圖的內存需求?
更高。 您已將節點大小(至少兩個指針)添加到每個元素。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.