[英]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 loop
和iterator-based loop
在执行时间方面的性能非常接近,并且都比index-based loop
快10x
左右。 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.