编译时“strlen()”有效吗?

时间:2009-09-08 02:39:40

标签: c++ string templates performance

有时需要将字符串的长度与常量进行比较 例如:

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 

好处是编译器在二进制输出中不包含“[]”字符串。

它是特定于编译器的优化还是常见行为?

4 个答案:

答案 0 :(得分:12)

为什么不

sizeof "[]" - 1;

(减去一个尾随空值。你可以 sizeof“[]” - sizeof'\ 0',但sizeof'\ 0' 通常是C中的sizeof(int),而“ - 1”是 完全可读。)

答案 1 :(得分:5)

内联函数调用的功能既是特定于编译器的优化,也是的常见行为。也就是说,许多编译器都可以这样做,但它们并不是必需的。

答案 2 :(得分:3)

我认为大多数编译器会在启用优化时将其优化 。如果他们被禁用,可能会使你的程序减慢到不必要的程度。

我更喜欢你的模板函数,因为它们保证在运行时不会调用strlen。 当然,不是为charwchar_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?老实说,我认为你的代码可读性较差,其他程序员会盯着你,就像你从过滤器中抽出旧咖啡一样。