strlen()编译时优化

时间:2016-04-03 19:13:17

标签: c++ arrays string c++11

几天前,我发现您可以使用以下内容找到编译时strlen

template<size_t N>
constexpr size_t strlen_(const char (&data)[N]) noexcept{
    return N - 1;
}

如果它被编译,那么一切都很好。你可以添加这样的重载:

size_t strlen_(const char *s) noexcept{
    return strlen(s);
}

然后它将始终编译。

我的问题是 - C ++ <cstring>是否使用了这样的东西,如果没有 - 为什么?

5 个答案:

答案 0 :(得分:8)

不,它没有。因为它给出了错误的答案。

char x[10] = "abc";
int correct_length   = std::strlen(x);  // 3
int incorrect_length = strlen_(x);      // 9

此外,对于2次重载,将永远不会调用模板。接受const char*的非模板一直是首选。

这并不意味着strlen不能在编译时用一些编译器魔法来计算。但是,使用正确的语言无法以这种方式完成。

答案 1 :(得分:4)

您的strlen_返回数组data的大小,而不是以null结尾的字符串的大小。正确的实施方式是:

constexpr size_t ct_strlen( const char* s ) noexcept
{
  return *s ? 1 + ct_strlen(s + 1) : 0;
}

答案 2 :(得分:3)

您的代码有问题。

令人惊讶的是,在strlen()上进行编译时优化的正确方法是调用strlen()。像clang这样的现代编译会在编译时知道长度时优化掉不必要的strlen()

此外,在大多数情况下sizeof派上用场时,程序员可以正确使用变量保持文字字符串。像:

const char foo[] = "Hello World";
size_t len = sizeof(foo)-1; // 11

请注意,这有一些假设,如果你这样做,你会给自己带来麻烦,但不能让你的生活变得简单:

const char foo[] = "Hello World\01234";
size_t len = sizeof(foo)-1; // 16

编辑:为了让明显更像是一个答案。

答案 3 :(得分:2)

您的strlen _不起作用:http://ideone.com/PNNeaX

另外:我知道visual studio 2015优化了所有类型的strlen调用,即使在我怀疑的情况下,当我检查汇编输出时,这些调用已经消失了runtime 1}} strlen来电。

正如@Calvin所说,Clang似乎也这样做。所以真的没有理由。

答案 4 :(得分:2)

来自ZDF的回复。

我做了测试,似乎过早优化。

代码:

#include <cstdio>
#include <cstring>

constexpr unsigned MAX = 1000 * 1000 * 250;


constexpr size_t strlen_c(const char* s) noexcept{
    return *s ? 1 + strlen_c(s + 1) : 0;
}


int main(){
    constexpr const char *s = "Hi, my name is Malcolm and I am very good boy...";

    unsigned sum = 0;

    for(unsigned i = 0; i < MAX; ++i){
        sum += strlen(s) + i;
    }

    return sum;
}

结果:

代码编译为:

gcc   x.cc -std=c++11 -Wall -Wpedantic
gcc   x.cc -std=c++11 -Wall -Wpedantic -O3
clang x.cc -std=c++11 -Wall -Wpedantic
clang x.cc -std=c++11 -Wall -Wpedantic -O3

这是花了多少时间:

------------------------------------
|         | GCC       | CLANG      |
------------------------------------
| len     | 0m1.506s  | 0m0.743s   |
| len O3  | 0m0.001s  | 0m0.002s   |
| lenc    | 1m5.476s  | 0m56.871s  |
| lenc O3 | 0m12.267s | 0m0.060s   |
------------------------------------

Clang看起来有点快,但经过全面优化后,constexpr strlen_c()没有得到回报。

如果我在代码中做错了,请告诉我。