简体   繁体   English

我应该使用哪个C ++ stl容器?

[英]Which C++ stl container should I use?

Imagine the following requirements: 想象一下以下要求:

measurement data should be logged and the user should be able to iterate through the data. 测量数据应该记录下来,用户应该能够遍历数据。

uint32_t timestamp;
uint16_t place;
struct SomeData someData;
  • have a timestamp ( uint32_t ), a place ( uint16_t ) and some data in a struct 在结构中具有时间戳记( uint32_t ),位置( uint16_t )和一些数据

  • have a constant number of datasets. 具有恒定数量的数据集。 If a new one arrives, the oldest is thrown away. 如果有新的,最旧的被扔掉。

  • the number of "place" is dynamic, the user can insert new ones during runtime “位置”的数量是动态的,用户可以在运行时插入新的

  • it should be possible to iterate through the data to the next newer or older dataset but only if the place is the same 只有在位置相同的情况下,才有可能遍历数据到下一个新的或更旧的数据集

  • need to insert at the end only 只需要在最后插入

  • memory should be allocated once at program start 程序启动时应分配一次内存

  • insertion need not to be fast but should not block other threads for a long time which might be iterating through the container 插入不必太快,但不应长时间阻塞其他线程,这可能会遍历容器

  • memory requirement should be low 内存需求应该低

EDIT: - The container should all the memory which is not used otherwise, therefore it can be large. 编辑:-容器应该所有否则不使用的内存,因此它可能很大。

I am not sure which container I should use. 我不确定应该使用哪个容器。 It is an embedded system and should not use boost etc. 这是一个嵌入式系统,不应使用boost等。

I see the following possibilities: 我看到以下可能性:

std::vector - drawbacks: The insertion at the end requires that all objects are copied and during this time another thread cannot access the vector. std :: vector-缺点:最后插入要求复制所有对象,在此期间,另一个线程无法访问该向量。 Edit: This can be avoided by implementing it as a circular buffer - see comments below. 编辑:这可以通过将其实现为循环缓冲区来避免-参见下面的注释。 When iterating throught the vector, I have to test the place ID. 当遍历向量时,我必须测试地点ID。 Maybe it might also be a problem to allocate much memory as one block - because the memory could be segmented? 将大量内存分配为一个块也许也可能是一个问题-因为内存可以分段?

std::deque - compared to std::vector insertion (and pop_back ) is faster but memory requirement? std::deque pop_backstd::vector插入(和pop_back )相比更快,但是需要内存吗? Iterators do not become invalid if the insertion is at the end. 如果插入在末尾,则迭代器不会变得无效。 But I still have to iterate and test the second ID ("place"). 但是我仍然必须迭代并测试第二个ID(“位置”)。 I think it does not need to allocate all the memory in one big block as it is the case with vector or array. 我认为不需要像矢量或数组那样在一个大块中分配所有内存。 If an element is added in front and another one is removed at the end (or removed first and added after), I guess there does no memory allocation take place? 如果在前面添加一个元素,然后在末尾删除另一个元素(或先删除然后添加),我猜是否没有发生内存分配?

std::queue - instead of deque, I should rather use a queue? std::queue我应该使用队列而不是双端队列? Is it true that in many implementations a queue ist implented just as a deque? 在许多实现中,是否确实像队列队列那样冒充了队列管理员?

std::map - Like deque any iterators to existing elements will not become invalid. std::map map-像双端队列一样,现有元素的任何迭代器都不会失效。 If I make the key a combination of place and timestamp, then iteration through the map is maybe faster because it is already sorted? 如果我将键组合为位置和时间戳,那么遍历地图的迭代速度可能会更快,因为它已经排序了? Memory requirements of a map? 一张图的内存要求?

std::multimap - as the number of places is not constant I cannot make a multimap with "place" as the index. std::multimap由于位数不是恒定的,因此我无法使用“ place”作为索引来制作多重地图。

std::list - has no advantage over deque here? std::list list-在这里比双端队列没有优势吗?

Some suggested the use of a circular buffer. 有些人建议使用循环缓冲区。 If I do not want that the memory is allocated as one big block I still have to use a container and most questions above stay valid. 如果我不希望将内存分配为一个大块,我仍然必须使用容器,并且上面的大多数问题仍然有效。

Update: I will use a ring buffer as suggested here but using a deque as the underlying container. 更新:我将使用此处建议的环形缓冲区,但使用双端队列作为基础容器。 In order to being able to scroll fast through the datasets with the preselected "place" I will eventually introduce two additional indices into the data struct which will point to the previous and the next index with the same place. 为了能够快速滚动带有预选“位置”的数据集,我最终将在数据结构中引入两个附加索引,这些索引将指向具有相同位置的上一个和下一个索引。

How much memory will be used? 将使用多少内存? In my special case the size of the struct is 56 bytes. 在我的特殊情况下,该结构的大小为56个字节。 The gnu lib uses 512 bytes as minimum block size, the IAR compiler 16 bytes. gnu lib使用512字节作为最小块大小,IAR编译器使用16字节。 Hence the used block size will be 512 or 56 bytes respectively. 因此,使用的块大小将分别为512或56个字节。 Besides two iterators (using 4 pointers each) and the size there will be a pointer stored for each block. 除了两个迭代器(每个使用4个指针)和大小外,每个块还将存储一个指针。 Therefore in the implementation of the iar compiler (block size 56 bytes) there will be 7 % overhead (on a 32 bit system) compared to the use of a std::vector or array. 因此,与使用std :: vector或数组相比,在iar编译器(块大小为56字节)的实现中,开销(在32位系统上)为7%。 In the gcc implementation there will fit 9 objects in the block (504 bytes) while 512 + 4 bytes are needed per block which is 2 % more. 在gcc实现中,将在块中容纳9个对象(504字节),而每个块需要512 + 4字节,这增加了2%。

The block size is not large but the continuous memory size needed for the pointer array is already relatively large, especially for the implementation where one block is one struct. 块大小不大,但是指针数组所需的连续内存大小已经相当大,尤其是对于一个块是一个结构的实现。

A std::list would need 2 pointers per struct which is 14 % overhead in my case on 32 bit systems. 一个std :: list每个结构将需要2个指针,在我的情况下,在32位系统上,这是14%的开销。

  1. std::vector

    ... the memory could be segmented? ...内存可以分段吗?

    No, std::vector allocates contiguous memory, as is documented in that link. 不, std::vector分配连续的内存,如该链接中所述。 Arrays are also contiguous, but you might just as well use vector for this. 数组也是连续的,但是您也可以使用向量。

  2. std::deque is segmented, which you said you didn't want. std::deque是分段的,您说过不需要。 Or do you want to avoid a single large allocated block? 还是要避免分配单个大块? It's not clear. 还不清楚

    Anyway, it has no benefit over vector if you really want a circular buffer (because you'll never be adding/removing elements from the front/back anyway), and you can't control the block size. 无论如何,如果您真的想要一个圆形缓冲区,它比矢量没有任何好处(因为无论如何您永远都不会从前/后添加/删除元素),并且您无法控制块的大小。

  3. std::queue

    ... Is it true that in many implementations a queue is implented just as a deque? ...在许多实现中,队列是否像双端队列一样被设置为真的吗?

    Yes, that's the default in all implementations. 是的,这是所有实现中的默认设置。 See the linked documentation or any decent book. 请参阅链接的文档或任何体面的书。

    It doesn't sound like you want a FIFO queue, so I don't know why you're considering this one - the interface doesn't match your stated requirement. 听起来好像不想要FIFO队列,所以我不知道您为什么要考虑这个队列-接口不符合您的要求。

  4. 'std::map` 'std :: map`

    ... iteration through the map is maybe faster because it is already sorted? ...通过地图迭代可能更快,因为它已经排序了?

    On most modern server/desktop architectures, map will be slower because advancing an iterator involves a pointer chase (which impairs pipelining) and a likely cache miss. 在大多数现代服务器/桌面体系结构上,映射会较慢,因为推进迭代器会涉及指针追逐(这会影响流水线操作)和可能的缓存未命中。 Your anonymous embedded architecture may be less sensitive to these effects, so map may be faster for you. 您的匿名嵌入式体系结构可能对这些影响不太敏感,因此映射可能对您来说更快。

    ... Memory requirements of a map? ...一张地图的内存需求?

    Higher. 更高。 You have the node size (at least a couple of pointers) added to each element. 您已将节点大小(至少两个指针)添加到每个元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM