Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::vector reserve()和push_back()比resize()和数组索引快,为什么?_C++_Optimization_Stl_Vector - Fatal编程技术网

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

C++ std::vector reserve()和push_back()比resize()和数组索引快,为什么?,c++,optimization,stl,vector,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(

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

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;
    }
}
void ConvertToFloat(const std::vector&audioBlock,
标准::矢量&输出)
{
常量浮动rcpShortMax=1.0f/(浮动)最大值;
out.resize(audioBlock.size());
对于(size_t i=0;i
我很高兴在最初非常幼稚的实现上有了更快的速度,处理65536个音频样本只需1毫秒

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

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 );
    }
}
void ConvertToFloat(const std::vector&audioBlock,
标准::矢量&输出)
{
常量浮动rcpShortMax=1.0f/(浮动)最大值;
out.reserve(audioBlock.size());
对于(size_t i=0;i
现在,我完全希望它能提供与原始代码完全相同的性能。然而,循环现在突然需要900usec(也就是说,它比其他实现快100usec)

有人能解释为什么这会带来更好的性能吗?
resize()
是否初始化reserve只分配但不构造的新分配向量?这是我唯一能想到的

PS这是在单芯2Ghz AMD Turion 64 ML-37上测试的

resize是否初始化reserve只分配但不构造的新分配向量

由于
out
的大小(=0)小于
audioBlock.size()
,因此会创建附加元素并附加到
out
的末尾。这将通过调用新元素的默认构造函数来创建新元素


Reserve只分配内存。

第一个代码写入
out[i]
,这可以归结为
begin()+i
(即添加)。第二个代码使用
push_back
,它可能会立即写入一个已知的指针,该指针相当于
end()
(即不添加)。通过使用迭代器而不是整数索引,可以使第一次运行的速度与第二次运行的速度一样快

编辑:还要澄清一些其他注释:向量包含浮点数,构造浮点数实际上是不可操作的(与声明“float f;”的方式相同;不发出代码,只告诉编译器为堆栈上的浮点数节省空间)。因此,我认为浮动向量的
resize()
reserve()
之间的任何性能差异都与构造无关

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

保留()

如果n小于或等于
容量()
,则此调用无效。否则,它将请求分配额外内存。如果请求成功,则
容量()
大于或等于n;否则,
capacity()
将保持不变。在这两种情况下,
size()
保持不变

如果向量中插入的元素超过
capacity()-size()
个,内存将自动重新分配。重新分配不会更改
size()
,也不会更改向量中任何元素的值。但是,它确实增加了容量()


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

SGI的STL参考解释了resize“在末尾插入或删除元素”,而reserve只负责内存分配。它将使用为向量设置的分配器。如果在resize/reserve调用后进行基准测试,您可以看到这是否是原因。@Eduardo-这可以使用向量分配器工作(您通常看不到,因为默认分配器“只适用于大多数应用程序”)。分配器有一个接口,该接口包括一个用于分配原始内存的函数(
allocate()
)和一个用于在该原始内存中就地构造对象的函数(
construct()
),以及其他函数<代码>分配()
很可能由
malloc()
实现,但这不是一个要求。查看Stephan T.Lavavej关于“Mallocator”的文章,了解如何工作:DDJ还有一篇Matt Ostern关于分配器的好文章:例行检查,编译代码时使用的是release而不是调试设置?呵呵,是的,我使用的是release。这更多的是一个关于帮助编译器帮助我的问题:)对不起,但是你的构造点是不真实的。浮动f=0.0f;显然比“float f;”慢。后者是一个nop,前者不是。哦,公平点,我不知道构造一个分配给它0的浮点。向量在调整大小时为每个元素指定T(),即float(),即0。不过,使用迭代器而不是整数索引可能会更快。“构造一个分配给它0的浮点数”不一定是真的。这两种方式都可以构建。否则你永远也用不到它。这里的问题是它是否初始化了值。至于使用迭代器的建议,请注意,如果可能的话,我建议使用指针;这样,您就可以确保不会从迭代器类中获得任何开销。不过,只有在真正热门的代码中才值得这么做;否则,迭代器通常是
out.resize( audioBlock.size() );