繁体   English   中英

使用标准的标准容器进行迭代

[英]iterating over std containers using standard for

从我学到的以std :: vector遍历容器的方式是使用迭代器,如下所示:

for(vector<int>::iterator it = numbers.begin(); it != numbers.end(); it++)

我的问题是,为什么不使用standatd for而不是在容器上for迭代,它更快,因为不需要调用numbers.begin()numbers.end()函数。
从我的尝试中,我发现使用for的速度比使用迭代器的速度快X 30。
我写了这段代码:

vector<int> numbers;
for (int i = 0; i < 5000000; i++)
{
    numbers.push_back(i);
}

time_t t = time(0);
struct tm * now = localtime(&t);
cout << now->tm_hour << ":" << now->tm_min << ":" <<  now->tm_sec << "\n";

for(vector<int>::iterator it = numbers.begin(); it != numbers.end(); it++)
{
    *it = 7;
}

t = time(0);
now = localtime(&t);
cout << now->tm_hour << ":" << now->tm_min << ":" <<  now->tm_sec << "\n";

int size = numbers.size();
for (int i = 0; i < size; i++)
{
    numbers[i] = i;
}

t = time(0);
now = localtime(&t);
cout << now->tm_hour << ":" << now->tm_min << ":" <<  now->tm_sec;

输出为:

    19:28:25
    19:28:56
    19:28:57

看一下您的数字-30秒迭代一个简单的向量? 那是CPU时间的永恒。 那里出问题了。

一些建议:

  • 该载体大约需要19MB。 数量不多,但是有可能导致堆碎片,或者如果计算机上加载了许多其他应用程序,则可能导致VM交换。 为了获得可靠的数字,请关闭尽可能多的应用程序,并确保系统空闲。

  • 提示位于计时器内部,因此您正在测量iostream库的各个部分的性能。 您停下时间之后计时部分之外进行侦察。

  • 一秒钟的时钟不够精确,无法衡量性能指标。 使用timeval和gettimeofday()获得微秒精度。

  • 仅对向量进行一次迭代,我就发现运行之间存在很大差异。 为了获得更多可重复的结果,请多次迭代向量(例如500次)。 (这比使用较大的向量更好,后者可能会导致交换/碎片问题。)

  • 打开优化(例如g ++ -O3)。 循环运行得更快,时间差也要少得多。 内联优化可能更有助于std :: vector <>代码。

有了这些更改(如下),在我的计算机上,迭代器的速度比没有优化的索引慢4倍,但使用-O1的迭代器要快一些 ,而使用-O3的迭代器则差不多。

#include <iostream>
#include <sys/time.h>
#include <vector>
using namespace std;

const unsigned N_REPS = 500;
const unsigned N_ITEMS = 5000000;

int print_elapsed(timeval start)
{
    timeval stop;
    gettimeofday(&stop, NULL);
    int elapsed = (stop.tv_sec * 1000000 + stop.tv_usec) - (start.tv_sec * 1000000 + start.tv_usec);
    cout << elapsed << "us" << endl;
    return elapsed;
}

int main()
{
    vector<int> numbers;
    numbers.reserve(N_ITEMS); // avoid heap fragmentation
    for (int i = 0; i < N_ITEMS; ++i)
        numbers.push_back(i);

    timeval start;
    gettimeofday(&start, NULL);

    for (unsigned r = 0; r < N_REPS; ++r)
        for (vector<int>::iterator it = numbers.begin(); it != numbers.end(); ++it)
            *it = r;

    int elapsed0 = print_elapsed(start);
    gettimeofday(&start, NULL);

    unsigned size = numbers.size();
    for (unsigned r = 0; r < N_REPS; ++r)
        for (unsigned i = 0; i < size; ++i)
            numbers[i] = r;

    int elapsed1 = print_elapsed(start);
    cout << 100 * float(elapsed1) / elapsed0 << '%' << endl;

    return 0;
}

使用迭代器可为您提供灵活性,即使您将容器类型更改为另一种,迭代代码也将保持不变。 这是因为所有标准库容器都提供了迭代器。 在某种程度上,它使您有机会编写更多通用代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM