有时需要将字符串的长度与常量进行比较 例如:
if ( line.length() > 2 )
{
// Do something...
}
但我试图避免在代码中使用“魔术”常量 通常我会使用这样的代码:
if ( line.length() > strlen("[]") )
{
// Do something...
}
由于函数调用,它更具可读性,但效率不高 我写了模板函数如下:
template<size_t N>
size_t _lenof(const char (&)[N])
{
return N - 1;
}
template<size_t N>
size_t _lenof(const wchar_t (&)[N])
{
return N - 1;
}
// Using:
if ( line.length() > _lenof("[]") )
{
// Do something...
}
在发布版本(VisualStudio 2008)中,它可以生成相当不错的代码:
cmp dword ptr [esp+27Ch],2
jbe 011D7FA5
好处是编译器在二进制输出中不包含“[]”字符串。
它是特定于编译器的优化还是常见行为?
答案 0 :(得分:12)
为什么不
sizeof "[]" - 1;
(减去一个尾随空值。你可以 sizeof“[]” - sizeof'\ 0',但sizeof'\ 0' 通常是C中的sizeof(int),而“ - 1”是 完全可读。)
答案 1 :(得分:5)
内联函数调用的功能既是特定于编译器的优化,也是的常见行为。也就是说,许多编译器都可以这样做,但它们并不是必需的。
答案 2 :(得分:3)
我认为大多数编译器会在启用优化时将其优化 。如果他们被禁用,可能会使你的程序减慢到不必要的程度。
我更喜欢你的模板函数,因为它们保证在运行时不会调用strlen
。
当然,不是为char
和wchar_t
编写单独的函数,而是可以添加另一个模板参数,并获得适用于任何类型的函数:
template <typename Char_t, int len>
int static_strlen(const Char_t (&)[N] array){
return len / sizeof(Char_t) - 1;
}
(正如评论中已经提到的,如果传递了一组整数,这将会产生有趣的结果,但是你可能会这样做吗?毕竟这是字符串的意思)
最后一点,名称_strlen
错误。名称空间范围内以下划线开头的所有名称都保留给实现。你冒着一些令人讨厌的命名冲突的风险。
顺便说一句,为什么“[]”比2的神奇常数少?
在这两种情况下,如果比较的字符串格式发生变化,则必须更改文字。
答案 3 :(得分:-7)
#define TWO 2
#define STRING_LENGTH 2
/* ... etc ... */
说真的,为什么要经历所有这些麻烦只是为了避免输入2?老实说,我认为你的代码可读性较差,其他程序员会盯着你,就像你从过滤器中抽出旧咖啡一样。