In loop condition: why is strlen() called every time, but vector.size() gets called only once?

Viewed 203

Code:

#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;

void f(const char* s) {
    for (size_t i = 0; i < strlen(s); i++) {
        printf("%c ", s[i]);
    }
}

void g(const vector<int>& v) {
    for (size_t i = 0; i < v.size(); i++) {
        printf("%d ", v[i]);
    }
}

Compile link: https://godbolt.org/z/PCi5yg

You will see the assembly code:

  • In function f(), strlen(s) gets called every time;
  • But in function g(), v.size() gets called only once.

Why is that?

The parameters are const, and they didn't change parameter in the inner loop.

1 Answers

You are misinterpreting the generated assembly. It's not that the vector's size is assumed unchanged, it's just that the call to v.size() is inlined. The vector's size is still computed anew every loop iteration and loaded into rax.

The const qualifier only prevents the functions f and g from modifying the object they refer to. It does not mean they can assume the object is truly immutable and cannot change in size. The compiler has to assume that non-inline functions could be changing the vector, and that includes printf. So the function has to re-compute the vector's size in order to be correct.

You can further convince yourself that the size is re-computed, even with optimization, by turning off inlining (-fno-inline). The generated assembly quite clearly demonstrates a call to vector::size.

Related