С какой целью я должен использовать 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
в его названии?
Один вариант использования был предложен в журнале доктора Добба от 1 июля 1996 г. для реализации алгоритмов:
Если буфер не может быть выделен или он меньше запрошенного, алгоритм по-прежнему работает правильно, он просто замедляется.
std::get_temporary_buffer
в C ++ 17 не рекомендуется.Ответы:
Страуструп говорит в «Языке программирования C ++» ( §19.4.4 , SE):
Он также начинает знакомство с двумя функциями с:
... но, похоже, нигде не дает определения временного или долгосрочного .
В анекдоте из «От математики к общему программированию» упоминается, что Степанов, однако, предоставил фиктивную реализацию заполнителя в исходном проекте STL:
источник
operator new
с последовательно уменьшающимися аргументами до тех пор, пока распределение не будет выполнено успешно. Никаких особых оптимизаций нет.crazy_allocator
get_temporary_buffer
. Однако, если мы получаем меньше запрошенной суммы (что было бы очень жаль), мы продолжаем пытаться работать с имеющимся у нас хранилищем. Может быть лучше, чем перехватыватьbad_alloc
исключения, вызванные попыткой выделить больше памяти, чем доступно. Однако настоящая полезность стоит и падает с хорошей реализацией.Специалист по стандартной библиотеке Microsoft говорит следующее ( здесь ):
источник
Стандарт говорит , что он выделяет для хранения до
n
элементов. Другими словами, ваш пример может вернуть буфер, достаточно большой только для 5 объектов.Тем не менее, довольно сложно представить себе хороший вариант использования для этого. Возможно, если вы работаете на платформе с очень ограниченным объемом памяти, это удобный способ получить «как можно больше памяти».
Но на такой ограниченной платформе, я полагаю, вы бы максимально обошли распределитель памяти и использовали бы пул памяти или что-то, что вы полностью контролируете.
источник
Функция устарела в C ++ 17, поэтому теперь правильный ответ - «ни с какой целью, не используйте ее».
источник
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 ) );
фактический размер базы должен быть больше или равен требуемому .
источник
Возможно (только предположение) это как-то связано с фрагментацией памяти. Если вы продолжаете интенсивно выделять и освобождать временную память, но каждый раз, когда вы это делаете, вы выделяете некоторую долгосрочную предполагаемую память после выделения временной памяти, но перед ее освобождением, вы можете получить фрагментированную кучу (я думаю).
Таким образом, get_temporary_buffer может быть задуман как кусок памяти большего размера, чем вам нужно, который выделяется один раз (возможно, есть много фрагментов, готовых для приема нескольких запросов), и каждый раз, когда вам нужна память, вы просто получаете один из куски. Таким образом, память не фрагментируется.
источник