Существует ли контейнер, который использует локальный буфер для небольшого количества элементов, и использует распределение кучи только тогда, когда количество элементов превышает определенный предел? Как и в большинстве реализаций std::string
.
Фон
Контейнер используется в следующем (упрощенном) контексте:
Foo foo; // some data
vector<HandlerPtr> tagged; // receives "tagged" items
// first pass: over all items in someList
for each(HandlerPtr h in someList)
{
h->HandleFoo(foo); // foo may become tagged or untagged here
if (foo.Tagged())
tagged.push_back(h);
}
for(auto itr=tagged.rbegin(); itr!=tagged.end(); ++itr)
{
// ...
}
Эта часть кода имеет высокую частоту вызова, но пометка элемента довольно редка, количество элементов в someContainer
обычно низкое, но несвязанное. Я не могу использовать предварительно выделенный "более глобальный" буфер. Цель состоит в том, чтобы избежать частого распределения.
Частота вызовов
Нет стандартного контейнера, который гарантирует такое поведение. Однако, если вы это сделаете, вы можете создать настраиваемый STL-совместимый класс распределителя, который извлекает из небольшого стекового буфера для небольших распределений и выполняет только распределение кучи, когда запрошенный размер распределения превышает размер буфера стека. Вы можете подключить свой собственный класс распределителя как второй параметр шаблона для std::vector<T, Alloc>
.
Для получения информации о создании настраиваемого распределителя вы должны прочитать эту статью.
Хотя это не гарантируется, большинство std::string
будут реализовывать Small String Optimization
, что просто (с VС++ 10 таким образом сохраняется 8 или 16 символов)
Я не видел vectors
делать это и всегда задавался вопросом, почему, но предстоящий стандарт С++ облегчит это с помощью std::aligned_storage
и alignof
. Таким образом, мы сможем получить правильно выровненную необработанную память и создать контейнеры с некоторым количеством "стековых" памяти по умолчанию.
vector
класс буфера. Стоимость копирования vector
значительно отличается от стоимости копирования трех указателей, потому что это включает в себя динамическое выделение (то есть вызов для allocate
) и глубокое копирование существующих данных. Поэтому я решил, что было бы дешевле просто зарезервировать дополнительное место. vector<Element, 4>
например. Однако я не знаю ни одного такого контейнера, но я, вероятно, попробую его дома, хотя всегда трудно соответствовать эффективности STL.