几天前,我发现您可以使用以下内容找到编译时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>
是否使用了这样的东西,如果没有 - 为什么?
答案 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()
没有得到回报。
如果我在代码中做错了,请告诉我。