C++ std::vector::clear()在代码重构后需要更多时间

C++ std::vector::clear()在代码重构后需要更多时间,c++,visual-c++,optimization,loops,stl,C++,Visual C++,Optimization,Loops,Stl,我有一个过程,用另一个数组中的值填充一些数组。 它看起来类似于以下代码: // Point 0 ptrlistVector.clear(); // Point 1 ptrlistVector.resize(50); const size_t s = ptrlistVector.size(); // Point 2 for (ObjectList::iterator j = objList.begin(); j != objList.end(); ++j) { for (UINT i

我有一个过程,用另一个数组中的值填充一些数组。 它看起来类似于以下代码:

// Point 0
ptrlistVector.clear();

// Point 1
ptrlistVector.resize(50);
const size_t s = ptrlistVector.size();

// Point 2
for (ObjectList::iterator j = objList.begin(); j != objList.end(); ++j)
{
    for (UINT i = 0; i < s; ++i) 
    {
        ptrlistVector[i].push_back(&(*j)); 
    }
}
// Point 3
//点0
ptrlistVector.clear();
//第1点
ptrlistVector.resize(50);
const size_t s=ptrlistVector.size();
//第2点
对于(ObjectList::iterator j=objList.begin();j!=objList.end();++j)
{
对于(UINT i=0;i
实际上,“push_back”行中有更复杂的代码-我将不同的值推送到一个列表中。这些值取决于某些条件

声明和定义:

typedef std::list<void*> ObjectPtrList;
typedef std::vector<ObjectPtrList> PtrListVector;
typedef std::list<std::string> ObjectList;

ObjectList objList;
PtrListVector ptrlistVector;
typedef std::list ObjectPtrList;
typedef std::vector PtrListVector;
typedef std::list ObjectList;
对象列表对象列表;
PtrListVector PtrListVector;
我测量了两个点之间的时间,以平均数计算,点1-0需要0.02秒,点3-2需要0.05秒。 我试图重构循环,发现了一些奇怪的行为。 我将上面的循环替换为以下内容:

for (UINT i = 0; i < s; ++i)
{
    for (ObjectList::iterator j = objList.begin(); j != objList.end(); ++j)
    {
        ptrlistVector[i].push_back(&(*j)); 
    }
}
for(UINT i=0;i
在那之后,时间改变了。点3-2需要0.035秒,但是clear()调用(点1-0)现在需要0.45秒(!!!),比上一次大得多

我使用MSVC10.0,在调试和发布模式下的结果大致相同。在释放模式下,时间差不是很明显,但无论如何,第二次释放的时间更大

有人能解释一下为什么在我更改循环后clear()调用要花费更多的时间吗

下面的代码是我用于性能测试的控制台应用程序

#include "stdafx.h"
#include <windows.h>
#include <vector>
#include <list>
#include <cstdio>
#include <cassert>
#include <string>

int _tmain(int argc, _TCHAR* argv[])
{
    typedef std::list<void*> ObjectPtrList;
    typedef std::vector<ObjectPtrList> PtrListVector;
    typedef std::list<std::string> ObjectList;

    ObjectList objList;
    objList.insert(objList.begin(), 500, std::string());

    PtrListVector ptrlistVector;

    LARGE_INTEGER __counters[10];
    double __totals[10] = { 0 };
    UINT __counter = 0;
    BOOL bRes;

    LARGE_INTEGER __freq;
    bRes = QueryPerformanceFrequency(&__freq);
    assert(bRes);

    for (int k = 0; k < 500; ++k)
    {
        // Point 0
        bRes = QueryPerformanceCounter(&__counters[0]);
        ptrlistVector.clear();

        // Point 1
        bRes = QueryPerformanceCounter(&__counters[1]);
        ptrlistVector.resize(50);
        const size_t s = ptrlistVector.size();

        // Point 2
        bRes = QueryPerformanceCounter(&__counters[2]);
        /*
        // original
        for (ObjectList::iterator j = objList.begin(); j != objList.end(); ++j)
        {
            for (UINT i = 0; i < s; ++i) 
            {
                ptrlistVector[i].push_back(&(*j)); 
            }
        }
        /*/
        for (UINT i = 0; i < s; ++i) // refactored
        {
            for (ObjectList::iterator j = objList.begin(); j != objList.end(); ++j)
            {
                ptrlistVector[i].push_back(&(*j)); 
            }
        }
        //*/

        // Point 3  
        bRes = QueryPerformanceCounter(&__counters[3]);
        __counter += 1;
        __totals[1] += 1.0 * (__counters[1].QuadPart - __counters[0].QuadPart) / __freq.QuadPart;
        __totals[2] += 1.0 * (__counters[2].QuadPart - __counters[1].QuadPart) / __freq.QuadPart;
        __totals[3] += 1.0 * (__counters[3].QuadPart - __counters[2].QuadPart) / __freq.QuadPart;
        __totals[4] += 1.0 * (__counters[3].QuadPart - __counters[0].QuadPart) / __freq.QuadPart;
        printf("%s: %.4f  %.4f  %.4f = %.4f\n", 
            __FUNCTION__, 
            __totals[1]/__counter, 
            __totals[2]/__counter, 
            __totals[3]/__counter, 
            __totals[4]/__counter);
    }
    return 0;
}
#包括“stdafx.h”
#包括
#包括
#包括
#包括
#包括
#包括
int _tmain(int argc,_TCHAR*argv[]
{
typedef std::list ObjectPtrList;
typedef std::vector PtrListVector;
typedef std::list ObjectList;
对象列表对象列表;
insert(objList.begin(),500,std::string());
PtrListVector PtrListVector;
大整数计数器[10];
双_总数[10]={0};
UINT uu计数器=0;
布尔布雷斯;
大整数频率;
bRes=查询性能频率(和频率);
断言(bRes);
对于(int k=0;k<500;++k)
{
//第0点
bRes=查询性能计数器(&_计数器[0]);
ptrlistVector.clear();
//第1点
bRes=查询性能计数器(&_计数器[1]);
ptrlistVector.resize(50);
const size_t s=ptrlistVector.size();
//第2点
bRes=查询性能计数器(&_计数器[2]);
/*
//原创的
对于(ObjectList::iterator j=objList.begin();j!=objList.end();++j)
{
对于(UINT i=0;i
我想在回答这个问题之前先说一句免责声明——这是猜测,因为我没有运行问题中的代码,也没有查看实际涉及的库实现。但我认为这概括了一个可能的解释,说明了问题中所描述的时间上的任何统计上的显著差异。但是,请记住,在这一点上,这只是猜测


清除列表向量所需时间的差异可能是由于堆的使用方式以及堆处理列表元素(列表被销毁时释放的列表元素)时可能正在进行的工作。我认为当列表元素被释放到第二个循环类型时,堆中可能会有更多的工作要做。我只能猜测(我还没有浏览库代码)

在第一种循环样式中,每个列表在每个循环迭代中添加一个元素;换句话说,循环迭代
0
在每个列表上放置一个元素,然后循环迭代
1
在每个列表上放置另一个元素,以此类推

在第二个示例中(其中
clear()
操作需要更长的时间),每个列表都是单独建立的;换句话说,
ptrlistVector[0]
中的列表被填充,然后
ptrlistVector[1]
被填充,依此类推

我猜对于第一个循环样式,特定列表中的每个元素与列表中的其他元素不连续(在地址空间中)。这是因为在对特定列表执行任何两次
push_back()
操作之间,会发生
50
其他分配以将元素添加到其他列表中

然而,我猜在第二个循环样式中,特定列表中的元素或多或少是连续的,因为这是分配发生的顺序

现在,让我们考虑一下当一个列表被销毁时这可能意味着什么(当保存列表的向量被清除时也会发生这种情况)。获取一个列表,其中