Зачем мне нужен std :: get_teilitary_buffer? - PullRequest
84 голосов
/ 16 июля 2010

Для каких целей я должен использовать std::get_temporary_buffer? Стандарт говорит следующее:

Получает указатель на хранилище, достаточное для хранения до n соседних объектов T.

Я думал, что буфер будет размещен в стеке, но это не так. Согласно стандарту C ++ этот буфер фактически не является временным. Какие преимущества имеет эта функция перед глобальной функцией ::operator new, которая также не создает объекты. Я прав, что следующие утверждения эквивалентны?

int* x;
x = std::get_temporary_buffer<int>( 10 ).first;
x = static_cast<int*>( ::operator new( 10*sizeof(int) ) );

Эта функция существует только для синтаксического сахара? Почему в его названии temporary?


Один случай использования был предложен в Dr. Журнал Добба, 01 июля 1996 года для реализации алгоритмов:

Если буфер не может быть выделен или если он меньше запрошенного, алгоритм по-прежнему работает правильно, он просто замедляется.

Ответы [ 6 ]

43 голосов
/ 16 июля 2010

Страуструп говорит на "Язык программирования C ++" ( §19.4.4 , SE):

Идея состоит в том, что система может поддерживать несколько буферов фиксированного размера, готовых к быстрому распределению, так что запрос пространства для n объектов может дать пространство для более чем n . Однако он также может дать меньше, поэтому один из способов использования get_temporary_buffer() - оптимистично запрашивать много, а затем использовать то, что оказывается доступным.
[...] Поскольку get_temporary_buffer() является низкоуровневым и, вероятно, будет оптимизирован для управления временными буферами, его не следует использовать в качестве альтернативы new или allocator :: allocate () для получения долговременного хранения.

Он также начинает знакомство с двумя функциями с:

Алгоритмы часто требуют временного пространства для приемлемой работы.

... но, похоже, не дает определения временных или долгосрочных в любом месте.

анекдот в «От математики к общему программированию» упоминает, что Степанов предоставил фиктивную реализацию заполнителя в оригинальном проекте STL, однако:

К своему удивлению, спустя годы он обнаружил, что все основные поставщики, которые предоставляют реализации STL, все еще используют эту ужасную реализацию [...]

17 голосов
/ 11 ноября 2014

Парень из стандартной библиотеки Microsoft говорит следующее ( здесь ):

  • Не могли бы вы объяснить, когда использовать 'get_teilitary_buffer'

Это имеет очень специализированное назначение.Обратите внимание, что он не генерирует исключения, как new (nothrow), но он также не создает объекты, в отличие от new (nothrow).

Он используется внутри STL в алгоритмах, подобных stable_partition ().Это происходит, когда есть волшебные слова, такие как N3126. 25.3.13 [alg.partitions] / 11: stable_partition () имеет сложность. «Максимум (последний - первый) * log (последний - первый) своп, но только линейное количество свопов, если естьдостаточно дополнительной памяти. "Когда появляются волшебные слова «если есть достаточно дополнительной памяти», STL использует get_teilitary_buffer (), чтобы попытаться получить рабочее пространство.Если это возможно, то он может реализовать алгоритм более эффективно.Если это невозможно, так как система работает опасно близко к нехватке памяти (или задействованные диапазоны огромны), алгоритм может вернуться к более медленной технике.

99,9% пользователей STL будутникогда не нужно знать о get_teilitary_buffer ().

9 голосов
/ 16 июля 2010

Стандарт гласит, что он выделяет хранилище для до n элементов. Другими словами, ваш пример может вернуть достаточно большой буфер только для 5 объектов.

Кажется, довольно сложно представить хороший вариант использования для этого. Возможно, если вы работаете на платформе с ограниченным объемом памяти, это удобный способ получить «как можно больше памяти».

Но на такой ограниченной платформе я бы подумал, что вы максимально обойдете распределитель памяти и будете использовать пул памяти или что-то, над чем у вас полный контроль.

2 голосов
/ 07 декабря 2017

Для каких целей я должен использовать std::get_temporary_buffer?

Функция устарела в C ++ 17, поэтому правильный ответ сейчас "без цели, не используйте его ".

2 голосов
/ 06 января 2012

Возможно (только предположение) это как-то связано с фрагментацией памяти. Если вы интенсивно продолжаете выделять и освобождать временную память, но каждый раз, когда вы делаете это, вы выделяете какую-то долгосрочную предполагаемую память после выделения временной, но до ее освобождения вы можете получить фрагментированную кучу (я полагаю).

Таким образом, get_teilitary_buffer может быть предназначен для того, чтобы быть частью памяти, которая больше, чем вам нужно, которая выделяется один раз (возможно, есть много блоков, готовых для принятия нескольких запросов), и каждый раз, когда вам нужна память, вы просто получаете один из кусков. Так что память не фрагментируется.

2 голосов
/ 16 июля 2010
ptrdiff_t            request = 12
pair<int*,ptrdiff_t> p       = get_temporary_buffer<int>(request);
int*                 base    = p.first;
ptrdiff_t            respond = p.sencond;
assert( is_valid( base, base + respond ) );

ответ может быть меньше запрос .

size_t require = 12;
int*   base    = static_cast<int*>( ::operator new( require*sizeof(int) ) );
assert( is_valid( base, base + require ) );

фактический размер base должен быть больше или равен 1012 * требуется *.

...