简体   繁体   English

for 循环或迭代器是遍历字符串的更快方法吗?

[英]Is a for-loop or iterator a faster way to traverse a string?

I have a string.我有一个字符串。

std::string strLine;

I can traverse the string chars using a if loop我可以使用if循环遍历字符串字符

for (int i = 0; strLine[i]; i++)

Another way i can do is using string iterator我可以做的另一种方法是使用字符串迭代器

string::iterator it;
for (it = strLine.begin(); it < strLine.end(); it++) 

Which is a faster and flexible way to iterate?哪种迭代方式更快、更灵活?

There are some issues with the example loops you've shown.您显示的示例循环存在一些问题。 Here's some common ways of iterating over a string:以下是迭代字符串的一些常用方法:

// index based loop
for (auto i = 0u; i < strLine.size(); ++i)
  cout << strLine[i];

// iterator based loop
for (auto i = strLine.begin(); i != strLine.end(); ++i)
  cout << *i;

// range-for loop
for (auto &c: s)
  cout << c;

All these versions have the same performance, since the compiler will generate basically the same code for all of them.所有这些版本都具有相同的性能,因为编译器将为所有版本生成基本相同的代码。

Inspired by @farassalem's answer with a benchmark, I added the following lines before running the same tests:受@farassalem 对基准的回答的启发,我在运行相同的测试之前添加了以下几行:

cout << "warming up for tests ...\n";
cout << strLine << endl;
cout << "warmed up for tests ...\n";

and you get essentially the same performance for all 3 versions:对于所有 3 个版本,您将获得基本相同的性能:

warming up for tests ...
This is a string!
warmed up for tests ...
This is a string!
index-based loop CPU time: 0.003 ms
index-based loop real time: 0.003264 ms
This is a string!
iterator-based loop CPU time: 0.003 ms
iterator-based loop real time: 0.003131 ms
This is a string!
range-for based loop CPU time: 0.002 ms
range-for based loop real time: 0.002728 ms

You should still pay close attention to how you benchmark before taking the results too seriously.在过于认真地对待结果之前,仍然应该密切关注基准测试的方式。

Check out this code printing a string This is a string!查看此代码打印字符串This is a string! : LIVE :直播

    cpu_time_start = clock();
    real_time_start = chrono::high_resolution_clock::now();

    for (auto i = 0u; i < strLine.size(); ++i)
        cout << strLine[i];
    cout << endl;

    cpu_time_end = clock();
    real_time_end = chrono::high_resolution_clock::now();
    cout << "index-based loop CPU time: " << 1000.0 * (cpu_time_end-cpu_time_start) / CLOCKS_PER_SEC << " ms\n"
         << "index-based loop real time: "<< chrono::duration<double, milli>(real_time_end-real_time_start).count() << " ms\n";

    //---------------------------------------------------------------------

    // get start time, same as above 
    for (auto i = strLine.begin(); i != strLine.end(); ++i)
        cout << *i;
    cout << endl;
    // get end time and print 

    //---------------------------------------------------------------------

    // get start time, same as above
    for (auto &c: strLine)
        cout << c;
    cout << endl;
    // get end time and print 

EDIT:编辑:

Thanks to @cigien, He pointed out to a more accurate way for benchmarking by warming up, It seems that they are a little bit close to each other in performance in terms of the time of execution, and if you change the order of loops in the code, it appears that any could be slightly faster than the other, I think that's due to caching, but yet I don't think that the compiler will produce the same code for them.感谢@cigien,他指出了一种通过预热来进行基准测试的更准确的方法,看起来它们在执行时间方面的性能有点接近,如果你改变循环的顺序代码,似乎任何一个都可能比另一个稍快,我认为这是由于缓存,但我不认为编译器会为它们生成相同的代码。 You can warm up by just printing out the string first before printing by iteration.您可以通过在迭代打印之前先打印出字符串来预热。 And maybe a more accurate way to compare them is to test each loop in one program on its own.也许更准确的比较它们的方法是单独测试一个程序中的每个循环。

This is the output when compiled with g++ -Wall -std=c++17 -O2 .这是使用g++ -Wall -std=c++17 -O2编译时的 output 。

warming up for tests ...
This is a string!
warmed up for tests ...
This is a string!
index-based loop CPU time: 0.008 ms
index-based loop real time: 0.005986 ms
This is a string!
iterator-based loop CPU time: 0.004 ms
iterator-based loop real time: 0.003417 ms
This is a string!
range-for based loop CPU time: 0.003 ms
range-for based loop real time: 0.002755 ms

I'll leave this part of the OLD ANSWER for people to know what happened:我将保留旧答案的这一部分,让人们知道发生了什么:

OLD OUTPUT !旧 OUTPUT !

This is a string!
index-based loop CPU time: 0.054 ms
index-based loop real time: 0.054416 ms
This is a string!
iterator-based loop CPU time: 0.005 ms
iterator-based loop real time: 0.004291 ms
This is a string!
range-for based loop CPU time: 0.004 ms
range-for based loop real time: 0.004308 ms

It looks that the range-for loop and the iterator-based loop are very close in performance in terms of the time of execution and both execute about 10x faster than the index-based loop .看起来range-for loopiterator-based loop在执行时间方面的性能非常接近,并且都比index-based loop10x左右。 Try larger length strings for more accurate results and run it many times and take the average.尝试更大长度的字符串以获得更准确的结果,并多次运行并取平均值。

You could also try compiling it on Compiler Explorer , I don't think the same code will be generated.您也可以尝试在Compiler Explorer上编译它,我认为不会生成相同的代码。

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

相关问题 将for循环迭代器添加到变量 - Adding for-loop iterator to variable For-Loop 带有负迭代器的“空”向量? - For-Loop a "Empty" Vector with negative iterator? 是什么在此for循环中重置迭代器的值? - What is resetting the value of the iterator in this for-loop? 迭代器for循环不会确认循环完成条件 - Iterator for-loop won't acknowledge loop finished condition 有没有办法比 O(n) 更快地访问多集树中的单个节点(使用迭代器并在循环中计算迭代次数)? [等候接听] - Is there a way to access single nodes from multiset tree faster than O(n)(using iterator and counting iterations in loop)? [on hold] 使用迭代器遍历列表? - Traverse a List Using an Iterator? 在 for 循环的某些迭代中,字符串的长度为 0,而在其他迭代中则为 0 - Length of string is 0 on some iterations of for-loop and not others 过滤迭代器循环(带提升)是否比内部带有 if 条件的经典 for 循环更快 - Are filtered iterator loops (with boost) faster than classical for loop with an if condition inside OpenMP - 在外部循环之前进行并行时,嵌套for循环变得更快。为什么? - OpenMP - Nested for-loop becomes faster when having parallel before outer loop. Why? 从基于迭代器的 for 循环转换后,如何在 map::find() 中调用方法? - How do I call method inside map::find() after converting from iterator-based for-loop?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM