Pic*_*tor 22 c++ optimization compiler-optimization c++11
Constexpr对编译优化非常有用.例如...
strlen(char*)
Run Code Online (Sandbox Code Playgroud)
可以使用....预编译
constexpr inline size_t strlen_constexpr(char* baseChar) {
return (
( baseChar[0] == 0 )
?(// if {
0
)// }
:(// else {
strlen_constexpr( baseChar+1 ) + 1
)// }
);
}
Run Code Online (Sandbox Code Playgroud)
这在优化时给它的运行时成本为"0"但是在运行时速度超过10 + x
// Test results ran on a 2010 macbook air
--------- strlen ---------
Time took for 100,000 runs:1054us.
Avg Time took for 1 run: 0.01054us.
--------- strlen_constexpr ---------
Time took for 100,000 runs:19098us.
Avg Time took for 1 run: 0.19098us.
Run Code Online (Sandbox Code Playgroud)
是否有任何现有的宏/模板黑客可以使用单个统一功能.即.
constexpr size_t strlen_smart(char* baseChar) {
#if constexpr
... constexpr function
#else its runtime
... runtime function
}
Run Code Online (Sandbox Code Playgroud)
或者一些超载黑客可以允许以下内容
constexpr size_t strlen_smart(char* baseChar) {
... constexpr function
}
inline size_t strlen_smart(char* baseChar) {
... runtime function
}
Run Code Online (Sandbox Code Playgroud)
注意:这个问题一般适用于概念.为运行时和constexpr提供2个单独的函数,而不是给出的示例函数.
免责声明:将编译器设置为-O3(优化级别)足以修复99.9%的静态字符串优化,使上面的所有示例"毫无意义".但这不是这个问题的重点,因为它适用于其他"例子",而不仅仅是strlen
.
Jan*_*dec 11
我不知道任何通用的方法,但我知道两种具体的情况.
另外gcc和clang复制了gcc的所有功能,它具有内置功能__builtin_constant_p
.我不确定gcc是否会正确地将内联函数的参数视为常量,但我担心你必须从宏中使用它:
#define strlen_smart(s) \
(__builtin_constant_p(s) && __builtin_constant_p(*s) ? \
strlen_constexpr(s) : \
strlen(s))
Run Code Online (Sandbox Code Playgroud)
可能有用.请注意,我正在测试constexpr s
和*s
constexpr,因为指向静态缓冲区的指针是一个编译时常量,而它的长度则不是.
对于特定的强制转换,strlen
您可以使用以下事实:字符串文字不是类型,const char *
而是const char[N]
隐式转换为的类型const char *
.但它也转换const char (&)[N]
为同时const char *
没有.
所以你可以定义:
template <size_t N>
constexpr size_t strlen_smart(const char (&array)[N])
Run Code Online (Sandbox Code Playgroud)
(显然strlen_smart
在const char *
前锋上strlen
)
我有时使用这种类型的参数的函数,即使在C++ 98中定义对应(我没有尝试重载strlen
自身,但重载是这样我可以避免调用它):
template <size_t N>
size_t strlen_smart(const char (&)[N]) { return N - 1; }
Run Code Online (Sandbox Code Playgroud)
这有问题
char buffer[10] = { 0 };
strlen_smart(buffer);
Run Code Online (Sandbox Code Playgroud)
应该说0,但是那个优化的变体只是说9.这些函数在这样的缓冲区上调用没有意义,所以我不在乎.