std :: vector reserve()和push_back()比resize()和数组索引更快,为什么?

Goz*_*Goz 38 c++ optimization stl vector

我正在对一段代码进行快速性能测试

void ConvertToFloat( const std::vector< short >& audioBlock, 
                     std::vector< float >& out )
{
    const float rcpShortMax = 1.0f / (float)SHRT_MAX;
    out.resize( audioBlock.size() );
    for( size_t i = 0; i < audioBlock.size(); i++ )
    {
        out[i]  = (float)audioBlock[i] * rcpShortMax;
    }
}
Run Code Online (Sandbox Code Playgroud)

我很高兴原来非常天真的实现速度超过1毫秒来处理65536个音频样本.

然而,只是为了好玩,我尝试了以下

void ConvertToFloat( const std::vector< short >& audioBlock, 
                     std::vector< float >& out )
{
    const float rcpShortMax = 1.0f / (float)SHRT_MAX;
    out.reserve( audioBlock.size() );
    for( size_t i = 0; i < audioBlock.size(); i++ )
    {
        out.push_back( (float)audioBlock[i] * rcpShortMax );
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我完全希望它能提供与原始代码完全相同的性能.然而,突然循环现在正在采用900usec(即它比其他实现快100usec).

谁能解释为什么这会带来更好的表现?是否resize()初始化新分配的向量,其中储备只是分配,但不建?这是我唯一能想到的.

PS这是在单核2Ghz AMD炫龙64 ML-37上测试的.

sep*_*p2k 62

resize是否初始化新​​分配的向量,其中reserve只分配但不构造?

是.

  • @Eduardo - 这可以使用分配器的分配器(你通常看不到,因为大多数应用程序的默认值'只适用').分配器有一个接口,它包括一个用于分配原始内存的函数(`allocate()`)和一个用于在原始内存(`construct()`)中就地构造对象的函数 - 以及其他函数.`allocate()`可能由`malloc()`实现,但这不是必需的.请参阅Stephan T. Lavavej关于"Mallocator"的文章,了解人们如何运作:http://blogs.msdn.com/vcblog/archive/2008/08/28/the-mallocator.aspx (2认同)

Sat*_*bir 6

调整大小()

修改容器,使其恰好有 n 个元素,如有必要,在末尾插入元素或从末尾删除元素。如果插入任何元素,则它们是 t 的副本。如果n > a.size(),该表达式等价于a.insert(a.end(), n - size(), t)。如果n < a.size(),则等价于a.erase(a.begin() + n, a.end())

预订()

如果 n 小于或等于capacity(),则此调用无效。否则,它是一个分配额外内存的请求。如果请求成功,则capacity()大于等于n;否则,capacity()不变。在任何一种情况下,size()都是不变的。

如果capacity() - size()在向量中插入了多个元素,内存将自动重新分配。重新分配不会改变size(),也不会改变向量的任何元素的值。然而,它确实增加了capacity()

Reserve 导致手动重新分配。使用的主要原因reserve()是效率:如果您知道向量最终必须增长到的容量,那么一次性分配所有内存通常比依赖自动重新分配方案更有效。