简体   繁体   English

std ::矢量推动速度?

[英]std::vector pushing speed?

I'm using vector to manage my large structure data. 我正在使用vector来管理我的大型结构数据。 But suddenly, when discovering vector source code, I am very surprised to see some code below : 但突然间,当发现vector源代码时,我很惊讶地看到下面的代码:

inline void push_back(const _Ty& _X)
    {insert(end(), _X); }
//...

void insert(iterator _P, size_type _M, const _Ty& _X)
    {
//////////////////////////////////////////////////////////////
        iterator _S = allocator.allocate(_N, (void *)0);
        iterator _Q = _Ucopy(_First, _P, _S);
        _Ufill(_Q, _M, _X);
        _Ucopy(_P, _Last, _Q + _M);
        _Destroy(_First, _Last);
        allocator.deallocate(_First, _End - _First);
//////////////////////////////////////////////////////////////
    }

It's the snippet code which "destroys" then reallocates its whole vector data. 这是“破坏”的代码片段,然后重新分配其整个矢量数据。 It's so annoying, because my structure has a large size and a vector has to manage hundreds of elements, while I only use vector::operator [] and vector::push_back() , especially pushing back takes most of my program time (it's time-consuming). 这太烦人了,因为我的结构有一个大的大小,一个向量必须管理​​数百个元素,而我只使用vector::operator []vector::push_back() ,特别是pushing back需要占用我的大部分时间(它是耗时的)。 In my case, is there any better container which can perform faster than std::vector , while I tried to google but no luck? 在我的情况下,有没有更好的容器可以比std::vector执行得更快,而我试图谷歌但没有运气?

The allocate-copy-delete (or allocate-move-delete in C++11) only happens once each time the vector exceeds its current capacity. 每次向量超过其当前容量时,只发生一次allocate-copy-delete(或C ++ 11中的allocate-move-delete) With each such reallocation, the capacity doubles. 每次这样的重新分配,容量增加一倍。 This averages out over time, so the amortized complexity of push_back() is constant. 这随着时间的推移而平均,因此push_back()摊销复杂性是不变的。

You can pre-allocate the vector's capacity by using its reserve() member function. 您可以使用其reserve()成员函数预先分配向量的容量。

在添加元素之前保留所需的所有空间可以解决您的问题吗?

Reallocation only occurs if your vector size increases past its capacity. 仅当您的矢量大小超过其容量时才会重新分配。 If you know in advance (even roughly) how many items your vector will contain, you can use its reserve member to pre-allocate enough capacity. 如果您事先知道(甚至大致)您的向量将包含多少项,您可以使用其预留成员预先分配足够的容量。 You can also trigger reallocation yourself in a controlled manner, even while filling the vector, to reduce the number of times it is called and thus get better performance. 即使在填充向量时,您也可以以受控方式自行触发重新分配,以减少调用的次数,从而获得更好的性能。

Now if you want guaranteed constant-time insertion there are containers that can be used for that but at a trade-off (eg. std::list will allocate lots of small memory blocks which may end up not any faster that your current vector use, because new is quite slow, and the memory usage will be more important too, and you lose random access, but sure every insertion will take roughly the same time as the others). 现在,如果你想要保证恒定时间插入,那么可以使用容器,但需要权衡(例如, std::list将分配大量的小内存块,这些内存块最终可能不会超过当前向量的使用速度,因为new很慢,而且内存使用也会更加重要,而且你会失去随机访问权限,但确保每次插入都会花费大致相同的时间)。

If you know your final data size, you can use reserve to preallocate the memory needed for the vector. 如果您知道最终数据大小,则可以使用reserve来预分配向量所需的内存。 That will remove all reallocating and copying. 这将删除所有重新分配和复制。

If you don't know the exact size, make an educated guess based on what you do know about your incoming data. 如果您不知道确切的大小,请根据您对传入数据的了解做出有根据的猜测。

A vector is a dynamically expanding container, but its contents are required to be in a contiguous block of memory (as I recall, this was unspecified in pre-C++11 but everybody did it). 向量是一个动态扩展的容器,但其内容需要在一个连续的内存块中(我记得,这在前C ++ 11中没有指定,但每个人都这样做)。 So if your vector already holds 8 elements, and the current capacity of the vector is 8 elements, then when you push_back a 9th element, the container must allocate new space for the larger capacity, copy the 8 elements that are already in the container, copy the 9th element into the new space, then destroy the old. 因此,如果你的向量已经拥有8个元素,并且向量的当前容量是8个元素,那么当你push_back第9个元素时,容器必须为更大的容量分配新的空间,复制已经在容器中的8个元素,将第9个元素复制到新空间,然后销毁旧元素。 If you are using C++11, and your elements support move-construction, then the 8 copies can become 8 moves. 如果您使用的是C ++ 11,并且您的元素支持移动构造,则8个副本可以变为8个移动。 Or if you want to incur the overheads of managing pointers, you could store pointers to elements instead of elements (copying a pointer is cheap, but now you need to deal with the lifespan issue). 或者如果你想要承担管理指针的开销,你可以存储指向元素而不是元素的指针(复制指针很便宜,但现在你需要处理生命周期问题)。

As for which container is faster than vector, that's a large open-ended question. 至于哪个容器比矢量快,这是一个很大的开放式问题。 It depends on all sorts of access/manipulation patterns. 它取决于各种访问/操作模式。 std::list was mentioned as a candidate. std :: list被提到作为候选人。 O(1) adding to the end of the list, but is probably a bigger O(1) than the amortized O(1) that vector uses. O(1)添加到列表的末尾,但可能比向量使用的摊销的O(1)更大的O(1)。 You lose random-access into the container. 您将失去对容器的随机访问权限。

Yes push_back() is known to be constant most of time, but needs to re-allocate the whole vector when the size() reach the capacity() . 是的, push_back()在大多数时候都是常量,但是当size()达到capacity()时需要重新分配整个向量。

If you want constant time insertion, you must try a std::list or a std::deque . 如果要插入常量时间,则必须尝试使用std::liststd::deque Especially a std::deque provides correct performance for insertion at the end of your container while being close to a vector in its interface. 特别是std::deque为容器末端的插入提供了正确的性能,同时接近其界面中的向量。

Extract from cpp reference : cpp引用中提取:

Therefore they provide a similar functionality as vectors, but with efficient insertion and deletion of elements also at the beginning of the sequence, and not only at its end. 因此,它们提供与向量类似的功能,但是在序列的开头也有效地插入和删除元素,而不仅仅是在其结尾。 But, unlike vectors, deques are not guaranteed to store all its elements in contiguous storage locations, thus not allowing direct access by offsetting pointers to elements. 但是,与矢量不同,deques不能保证将其所有元素存储在连续的存储位置,因此不允许通过将指针偏移到元素来直接访问。

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

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