为什么这个C++字符串长度计算函数比另一个更快

Why is this C++ string length calculation function faster than this other one?

本文关键字:函数 另一个 计算 C++ 字符串 为什么      更新时间:2023-10-16

我们的讲师解释说,这个计算字符串长度的函数......

int strlen_1(const char *str) {
    const char *temp = str;
    while(*temp != '') {
        temp++;
    }
    return temp - str;
}

。会比这个计算得更快...

int strlen_03(const char *str) {
    int i;
    for (i = 0; *(str+i) != ''; i++);
    return i;
我想他说这与算术计算

有关,就像在第一个中完成了任何算术计算一样,但我无法理解,我将它们都放在同一个水平上。你能用换句话说解释一下原因吗?

附言。我确实理解指针,我可以理解发生了什么,这就像一个单元逐步浏览存储在"RAM 单元"中的数组元素。

提前谢谢。

暂时

忽略优化,只看纸质算法:

前者反复执行此计算:

addr++

通过差值计算计算结果

addr1 - addr0

后者重复执行这些计算

addr0 + i
i++

结果由值返回计算

i

换句话说,在循环完成的工作量是原来的一半,以便在计算最终结果时完成一半的工作。

进入优化的 ASM,第一个在我的叮当声上的 -O3 处生成这个:

0x100000ee4:  cmpb   $0, 1(%rbx)
0x100000ee8:  leaq   1(%rbx), %rbx
0x100000eec:  sete   %al
0x100000eef:  testb  $1, %al
0x100000ef1:  je     0x100000ee4

第二个生成这个:

0x100000f09:  incl   %ebx
0x100000f0b:  cmpb   $0, (%rax)
0x100000f0e:  leaq   1(%rax), %rax
0x100000f12:  sete   %cl
0x100000f15:  testb  $1, %cl
0x100000f18:  je     0x100000f09

我省略了返回值的常量一次性器,因为它们不是循环复杂性的核心。优化器非常好,注意到唯一的主要区别是单个:

0x100000f09:  incl   %ebx

这是你的i

这是一个微优化,现代编译器最终可能会为两者生成相同的程序集,但对于非优化版本,原因如下:

int strlen_1(const char *str) 
{
    const char *temp = str; // declare the iterator
    while(*temp != '')   // dereference the pointer
                           // test the iterator 
    {
        temp++; // increment the iterator
    }
    return temp - str; // pointer subtraction
}

对于长度为 N 的字符串,这将为您提供 3N + 2 个操作。

int strlen_03(const char *str) 
{
    int i; // declare your iterator
    for (i = 0; *(str+i) != ''; i++); // initialize the iterator
                                        // add i to str
                                        // dereference that pointer value
                                        // test it against 
                                        // increment i
    return i;
}

对于同一字符串,这将为您提供 4N + 2 个操作。

同样,现代编译器可能会为您解决此问题,即使对于大多数字符串(仅适用于非常长的字符串),即使在未优化的形式中,这个小循环也不太可能产生太大差异。