为什么我需要std :: get_temporary_buffer?

时间:2010-07-16 11:25:39

标签: c++ memory-management stl buffer temporary

出于什么目的我应该使用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. Dobb's Journal, July 01, 1996中建议使用一个用例来实现算法:

  

如果没有缓冲区可以分配,或者它小于请求的缓冲区,算法仍能正常工作,它只会减慢速度。

6 个答案:

答案 0 :(得分:42)

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

  

这个想法是系统可以保留一些固定大小的缓冲区,以便快速分配,这样 n 对象的请求空间可能会产生超过 n 的空间。然而,它也可能产生更少的收益,因此使用get_temporary_buffer()的一种方法是乐观地要求很多,然后使用可能发生的事情。
  [...]因为get_temporary_buffer()是低级的并且可能针对管理临时缓冲区进行了优化,所以不应将其用作 new allocator :: allocate的替代方法()以获得更长期的存储空间。

他还开始介绍这两个函数:

  

算法通常需要临时空间来执行。

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

anecdote中的"From Mathematics to Generic Programming"提到Stepanov在原始STL设计中提供了虚假的占位符实现,但是:

  

令他惊讶的是,多年后他发现提供STL实施的所有主要供应商仍在使用这种可怕的实现[...]

答案 1 :(得分:17)

微软的标准图书馆人员说以下内容(here):

  
      
  • 您是否可以解释何时使用&#39; get_temporary_buffer&#39;
  •   
     

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

     

STL在诸如stable_partition()之类的算法中内部使用它。   当有像N3126 25.3.13这样的神奇单词时会发生这种情况   [alg.partitions] / 11:stable_partition()具有复杂性&#34;最多(最后    - 首先)* log(last - first)交换,但是如果有足够的额外内存,则只有交换的线性数量。&#34;当有魔力的话语时,如果有的话   足够的额外记忆&#34;出现,STL使用get_temporary_buffer()来   试图获得工作空间。如果可以,那么它可以实现   算法更有效率。如果它不能,因为系统正在运行   危险地接近内存不足(或涉及的范围很大),   算法可以回归到较慢的技术。

     

99.9%的STL用户永远不需要了解get_temporary_buffer()。

答案 2 :(得分:9)

标准表示它为最多 n元素分配存储空间。 换句话说,您的示例可能会返回一个足以容纳5个对象的缓冲区。

看起来很难想象一个好的用例。也许如果你正在一个内存受限的平台上工作,这是获得“尽可能多的内存”的便捷方式。

但是在这样一个受限制的平台上,我想你会尽可能地绕过内存分配器,并使用内存池或你可以完全控制的东西。

答案 3 :(得分:2)

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 的实际大小必须大于或等于 require

答案 4 :(得分:2)

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

所以get_temporary_buffer可能是一个比你需要更大的内存块,它被分配一次(也许有很多块可以接受多个请求),每次你需要内存时你就得到了其中一个块。所以内存不会碎片化。

答案 5 :(得分:2)

  

我应该使用std::get_temporary_buffer?

The function在C ++ 17中已被弃用,所以正确的答案现在是“无目的,不要使用它”。