处于循环状态:为什么每次都调用strlen(),但是vector.size()仅被调用一次?

时间:2018-10-28 14:07:29

标签: c++ gcc assembly

代码:

#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]);
    }
}

编译链接:https://godbolt.org/z/PCi5yg

您将看到汇编代码:

  • 在函数f()中,每次strlen(s)都会被调用;
  • 但是在功能g()中,v.size()仅被调用一次。

那是为什么?

参数是const,它们在内部循环中没有更改参数。

1 个答案:

答案 0 :(得分:8)

您误解了生成的程序集。并不是假定矢量的大小保持不变,而是内联了对v.size()的调用。向量的大小仍会在每次循环迭代时重新计算,并加载到rax中。

const限定符仅阻止函数fg修改它们引用的对象。这并不意味着他们可以假定对象是真正不变的,并且不能更改大小。编译器必须假定非内联函数可能正在更改矢量,并且其中包括printf。因此该函数必须重新计算向量的大小才能正确。

您可以进一步说服自己,turning off inlining (-fno-inline)甚至重新优化了大小。生成的程序集非常清楚地演示了对vector::size的调用。