什么是 strlen 省略?

What is strlen elision?

我可以 see it listed 作为现代 C++ 习语之一,但它到底是什么?

只是copy elision的一种吗?

恕我直言,self-evident 在我看来,如果编译器理解 strlen 的语义,并且在编译时知道所讨论的字符串,那么编译器就可以发出一个常量而不是在运行时评估字符串的长度(通过任何方式)。这就是这里发生的一切。相信 Microsoft 的营销部门 hype-up 如此简单的功能。

对这一切感兴趣的是(优化)编译器越来越倾向于将常用的运行时库函数视为内在函数,并尽可能为它们生成更好的代码。这已经持续了一段时间——memcpy 和 memset 是明显的例子——但我最近在 Godbolt 的编译器资源管理器中玩耍,很惊讶地看到 gcc 取代了它:

printf (" ");

有了这个:

putchar (' ');

震惊?我也是,我不确定我是否喜欢它。我可能有一个自定义的 printf 来做一些特别的事情,这种诡计会让人大吃一惊。在我看来,这么小的收益冒着很大的风险(编译器作者)。

您可能知道 std::strlen 遍历整个字符串。在某些情况下,这可能效率低下,因为这意味着 CPU 必须开始计算字符,这会减少其他内容的缓存位置。

但在大多数情况下,编译器能够优化 std::strlen 并计算字符串本身的字符数,而不是让生成的程序这样做。这有时称为 strlen 省略(因为它省略了对 strlen 的调用)。

std::strlensimple example 会完全优化。

#include <cstring>

int main() {
    return std::strlen("hi");
}

-O3 下生成的程序集是

main: # @main
  mov eax, 2
  ret

under -O0都没有产生循环!

现在这是一个相当简单的示例,但它甚至可以用于 std::strlen.

的更复杂的用法
#include <cstring>

int main(int argc, char**) {
    const char *string;
    if (argc == 1)
        string = "hello";
    else if (argc == 2)
        string = "world";
    else if (argc == 3)
        string = "!";

    return std::strlen(string); 
}

这里的字符串完全optimized away,还有std::strlen调用