Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using size() for the 2nd expression in a for construct always bad?

Tags:

c++

In the following example should I expect that values.size() will be called every time around the loop? In which case it might make sense to introduce a temporary vectorSize variable. Or should a modern compiler be able to optimize the calls away by recognising that the vector size cannot change.

double sumVector(const std::vector<double>& values) {
    double sum = 0.0;
    for (size_t ii = 0; ii < values.size(); ++ii) {
        sum += values.at(ii);
    }
}

Note that I don't care if there are more efficient methods to sum the contents of a vector, this question is just about the use of size() in a for construct.

like image 785
Tom Williams Avatar asked Oct 03 '08 12:10

Tom Williams


2 Answers

Here's one way to do it that makes it explicit - size() is called only once.

for (size_t ii = 0, count = values.size();  ii < count;  ++ii)

Edit: I've been asked to actually answer the question, so here's my best shot.

A compiler generally won't optimize a function call, because it doesn't know if it will get a different return value from one call to the next. It also won't optimize if there are operations inside the loop that it can't predict the side effects of. Inline functions might make a difference, but nothing is guaranteed. Local variables are easier for the compiler to optimize.

Some will call this premature optimization, and I agree that there are few cases where you will ever notice a speed difference. But if it doesn't make the code any harder to understand, why not just consider it a best practice and go with it? It certainly can't hurt.

P.S. I wrote this before I read Benoit's answer carefully, I believe we're in complete agreement.

like image 158
Mark Ransom Avatar answered Nov 16 '22 22:11

Mark Ransom


It all depends on what the vector's size implementation is, how aggressive the compiler is and if it listen/uses to inline directives.

I would be more defensive and introduce the temporary as you don't have any guarantees about how efficient your compiler will be.

Of course, if this routine is called once or twice and the vector is small, it really doesn't matter.

If it will be called thousands of times, then I would use the temporary.

Some might call this premature optimization, but I would tend to disagree with that assessment.
While you are trying to optimize the code, you are not investing time or obfuscating the code in the name of performance.

I have a hard time considering what is a refactoring to be an optimization. But in the end, this is along the lines of "you say tomato, I say tomato"...

like image 12
Benoit Avatar answered Nov 16 '22 23:11

Benoit