Ответ 1
Скорее всего, это не проблема. Deque
в любом случае выделять куски, поэтому вы, вероятно, перераспределите несколько раз. Вы определили это как узкое место?
Во всяком случае, стандарт не предоставляет аксессуар в контейнер "queue", потому что это победит цель инкапсуляции.
Если вы действительно волнуетесь, пул распределяет. Это означает предварительную выделение памяти, поэтому, когда контейнер запрашивает память, он уже существует. Я не могу по-настоящему разобраться с дистрибуторами и родственниками, это было бы излишним для ответа SO, но посмотрите распределители в Google.
В принципе, вы можете сообщить своему контейнеру, откуда его получить. Обычно это распределитель по умолчанию, который использует новые и удаляет.
Boost предоставляет диспетчер пулов, и он будет выглядеть примерно так:
#include <list>
#include <queue>
// pool
#include <boost/pool/pool_alloc.hpp>
// helpful typedef's
typedef boost::fast_pool_allocator<int> BoostIntAllocator;
typedef boost::singleton_pool<boost::fast_pool_allocator_tag, sizeof(int)> BoostIntAllocatorPool;
int main(void)
{
// specify the list as the underlying container, and inside of that,
// specify fast_pool_allocator as the allocator. by default, it preallocates
// 32 elements.
std::queue<int, std::list<int, BoostIntAllocator > > q;
/* No memory allocations take place below this comment */
for (int i = 0; i < 31; ++i)
{
q.push(i);
}
/* End no allocation */
// normally, the memory used by the singleton will
// not be free'd until after the program is complete,
// but we can purge the memory manually, if desired:
BoostIntAllocatorPool::purge_memory();
};
Пул выделяет память вверх, поэтому фактическое выделение памяти не выполняется во время push()
/pop()
.
Я использовал list
вместо Deque
, потому что он проще. Обычно Deque
превосходит list
, но с распределителем вещи, которые дали преимущество Deque
, такие как производительность кэша и распределение стоимость больше не существует. Поэтому a list
гораздо проще использовать.
Вы также можете использовать круговой буфер, например:
#include <queue>
// ring
#include <boost/circular_buffer.hpp>
int main(void)
{
// use a circular buffer as the container. no allocations take place,
// but be sure not to overflow it. this will allocate room for 32 elements.
std::queue<int, boost::circular_buffer<int> > q(boost::circular_buffer<int>(32));
/* No memory allocations take place below this comment */
for (int i = 0; i < 31; ++i)
{
q.push(i);
}
/* End no allocation */
};