Search code examples
c++stringperformancec++11

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

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 ?


Solution

  • Check out this code printing 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. 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.

    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 !

    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. 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.