Cpp Core Guidelines 在这个例子中浪费了什么?

What is wasted in this example from the Cpp Core Guidelines?

Cpp 核心指南中的示例浪费了什么?

P.9: Don't waste time or space

[...]

void lower(zstring s)
{
    for (int i = 0; i < strlen(s); ++i) s[i] = tolower(s[i]);
}

Yes, this is an example from production code. We leave it to the reader to figure out what's wasted.

来自 https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rp-waste

每次循环迭代都会计算 strlen。

strlen 每次检查循环条件时调用,每次调用花费 O(n) 时间,因此循环的总时间为 O(n^2).

由于代码的作者在循环中递增s,而不是i,因此浪费了很多时间并且可能会出现段错误:

for (int i = 0; i < strlen(s); ++s)
                 //right here ^^^^

正如其他回答者已经指出的那样,strlen(s) 被多次调用,因为它处于条件中,这意味着它应该被缓存并重用。

但是 strlen(s) 实际上根本不需要调用! s 是(或可隐式转换为)一个以 nul 结尾的 char 数组,因为那是 strlen 所期望的。所以我们可以将这个 属性 用于我们自己的循环。

void lower(zstring s) {
    for (char *p = s; *p; ++p)
        *p = std::tolower((unsigned char)*p);
}

除非它们在 zstring class 中有任何非常不直观的语义,否则当前形式的函数完全是在浪费时间 space,因为它的 "result" 不能在函数之后使用 - 它作为值传入,不会返回。

所以为了避免浪费时间去无用地计算不能使用的小写字母,以及space在复制传递的参数时,我会按引用传递!