Зачем мне нужен std:: получить временный буфер?

С какой целью я должен использовать 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 на свое имя?


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

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

6 ответов


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

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

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

алгоритмы часто требуют временного пространства, чтобы выполнить успешно.

... но, похоже, не дает определения временное или


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

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

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

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

99.9% пользователей STL никогда не будут знать о get_temporary_buffer().


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

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

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


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 ) );

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


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

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


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

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