Is using string.length() in loop efficient?

20.7k views Asked by At

For example, assuming a string s is this:

for(int x = 0; x < s.length(); x++)

better than this?:

int length = s.length();
for(int x = 0; x < length; x++)
6

There are 6 answers

3
Matthieu M. On BEST ANSWER

In general, you should avoid function calls in the condition part of a loop, if the result does not change during the iteration.

The canonical form is therefore:

for (std::size_t x = 0, length = s.length(); x != length; ++x);

Note 3 things here:

  • The initialization can initialize more than one variable
  • The condition is expressed with != rather than <
  • I use pre-increment rather than post-increment

(I also changed the type because is a negative length is non-sense and the string interface is defined in term of std::string::size_type, which is normally std::size_t on most implementations).

Though... I admit that it's not as much for performance than for readability:

  • The double initialization means that both x and length scope is as tight as necessary
  • By memoizing the result the reader is not left in the doubt of whether or not the length may vary during iteration
  • Using pre-increment is usually better when you do not need to create a temporary with the "old" value

In short: use the best tool for the job at hand :)

0
Tim Martin On

It depends on your C++ implementation / library, the only way to be sure is to benchmark it. However, it's effectively certain that the second version will never be slower than the first, so if you don't modify the string within the loop it's a sensible optimisation to make.

0
Alexander Gessler On

It depends on the inlining and optimization abilities of the compiler. Generally, the second variant will most likely be faster (better: it will be either faster or as fast as the first snippet, but almost never slower).

However, in most cases it doesn't matter, so people tend to prefer the first variant for its shortness.

0
Murali VP On

Is s.length() inline and returns a member variable? then no, otherwise cost of dereferencing and putting stuff in stack, you know all the overheads of function call you will incur for each iteration.

0
Bo Persson On

How efficient do you want to be?

If you don't modify the string inside the loop, the compiler will easily see than the size doesn't change. Don't make it any more complicated than you have to!

1
FluorescentGreen5 On

Although I am not necessarily encouraging you to do so, it appears it is faster to constantly call .length() than to store it in an int, surprisingly (atleast on my computer, keeping in mind that I'm using an MSI gaming laptop with i5 4th gen, but it shouldn't really affect which way is faster).

Test code for constant call:

#include <iostream>

using namespace std;

int main()
{
    string g = "01234567890";
    for(unsigned int rep = 0; rep < 25; rep++)
    {
        g += g;
    }//for loop used to double the length 25 times.
    int a = 0;
    //int b = g.length();
    for(unsigned int rep = 0; rep < g.length(); rep++)
    {
        a++;
    }
    return a;
}

On average, this ran for 385ms according to Code::Blocks

And here's the code that stores the length in a variable:

#include <iostream>

using namespace std;

int main()
{
    string g = "01234567890";
    for(unsigned int rep = 0; rep < 25; rep++)
    {
        g += g;
    }//for loop used to double the length 25 times.
    int a = 0;
    int b = g.length();
    for(unsigned int rep = 0; rep < b; rep++)
    {
        a++;
    }
    return a;
}

And this averaged around 420ms.

I know this question already has an accepted answer, but there haven't been any practically tested answers, so I decided to throw my 2 cents in. I had the same question as you, but I didn't find any helpful answers here, so I ran my own experiment.