为什么我需要std :: get_temporary_buffer?

为了什么目的,我应该使用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


Dobb's Journal博士在1996年7月1日提出了一个用例来实现algorithm:

如果没有缓冲区可以分配,或者如果它小于请求,algorithm仍然正常工作,它只是减慢速度。

Stroustrup在“C ++编程语言”§19.4.4 ,SE)中说:

这个想法是,一个系统可能会保留一些固定大小的缓冲区,以便为快速分配做准备,因此请求n个对象的空间可能会产生大于n的空间。 然而,它也可能产生较less,所以使用get_temporary_buffer()一种方式是乐观地要求很多,然后使用碰巧可用的东西。
[…]因为get_temporary_buffer()是低级别的,可能会优化pipe理临时缓冲区,所以不应该用newallocator :: allocate()的替代方法来获得长期存储。

他还开始介绍这两个function:

algorithm通常需要临时空间来执行可接受的操作。

…但似乎没有提供任何地方的临时长期的定义。

“从math到generics编程”中的一个轶事提到Stepanov在原始的STLdevise中提供了一个假的占位符实现,但是:

令他惊讶的是,他多年后才发现,所有提供STL实现的主要供应商仍在使用这个可怕的实现scheme,

微软的标准库家伙说以下( 这里 ):

  • 你可以解释什么时候使用'get_temporary_buffer'

它有一个非常专业的目的。 请注意,它不会像new(nothrow)那样抛出exception,但它也不会构造对象,不像new(nothrow)。

它在像stable_partition()这样的algorithm中被STL内部使用。 这种情况发生在有像N3126那样的神奇单词的时候。25.3.13 [alg.partitions] / 11:stable_partition()具有复杂性“至多(last – first)* log(last – first)交换,但只有线性交换是足够的额外的记忆。“ 当出现魔语“如果有足够的额外内存”时,STL使用get_temporary_buffer()尝试获取工作空间。 如果可以的话,那么它可以更有效地实现algorithm。 如果不行,因为系统运行的危险性接近内存不足(或涉及的范围很大),algorithm可能会回落到较慢的技术。

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

回应可能less于要求

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

底座的实际尺寸必须大于或等于要求

也许(只是猜测)它与内存碎片有关。 如果你持续地分配和释放临时内存,但是每次你分配临时内存时分配了一些长期的内存,但是在释放临时内存之前,你可能会得到一个碎片堆(我猜)。

所以get_temporary_buffer可能是一个比你需要的内存大的块(也许有很多块可以接受多个请求),每次你需要内存时,你只需要一个块。 所以内存不会被分割。