首先,除非你的函数真的对时间敏感,否则不要试图过度优化。只需使用您提供的那个,因为它很容易验证正确性,并且它不会仅仅为了它而变得聪明。
如果该功能确实需要快速,那么有很多方法可以对其进行更多优化。很多,真的很多方法。其中一些要么期望或假设您拥有的字符串的特定内存布局(例如,它们被分配在字边界上,并且分配也总是填充到字边界)。所以你需要小心,因为该算法可能适用于处理器、编译器和内存分配器的某种组合,而在其他方面可能会失败。
只是为了它,我将列出一些加速字符计数器的可能方法:
- 一次读取字符串一个单词(32 位或 64 位整数)。由于 L1 缓存和推测/无序执行,不一定有很大帮助。这需要对最后一个字进行循环结束调整(NUL 终止符后的字节数错误)。仅与字对齐和填充内存分配器一起使用。
- 删除条件,而是计算所有字符的计数(到数组)并返回所需字符的计数。(这将删除条件,如果您事先知道字符串长度,它可以实现出色的循环展开,并删除一个条件分支点。)
- 如果您事先知道字符串的长度(在其他地方计算),您可以使用它来展开循环。或者更好的是,将其编写为 for 循环并应用合适的 #pragma 和编译器选项,以使编译器为您执行循环展开。
- 用汇编程序编写例程。在走这条路之前,先启动所有编译器优化并反汇编例程——你可能会发现编译器已经使用了你知道的所有潜在技巧,还有一些你没有使用。
- 如果您的字符串可能非常大(兆字节)——我在这里推测——通过 OpenCL/CUDA 使用显卡可能会提供一些潜力。
等等。
但是,如果您遇到实际问题,我真的非常建议您坚持使用现有的解决方案。如果这是一个玩具问题,并且您正在优化它的乐趣,请继续。
循环剃须是学习 CPU 和指令集的一种有趣方式,但对于 99.999999...% 的编程任务来说,不值得付出努力。