有没有办法让这个tolower(...)代码更快?

时间:2015-11-12 07:10:55

标签: c++ c++11

浏览网页后,我想出了以下代码,将char16_t *字符串转换为小写字母。

速度在我的应用程序中非常重要,所以我想知道是否有办法让这个功能更快?

std::u16string ToLower(const char16_t* str)
{
  std::u16string data(str ? str : u"");
  std::u16string ldata;
  for (std::u16string::const_iterator it = data.begin(); it != data.end(); ++it)
  {
    ldata.push_back( std::use_facet<std::ctype<char16_t>>(std::locale()).tolower(*it) );
  }
  return ldata;
}

我的一部分认为&#34; push_back(...)&#34;部分本身并不是最有效的。

也许我甚至根本不能使用std :: u16string而是返回一个char16_t *并让调用函数删除该指针。

// pseudo code - untested
// edited with suggestion from @Dietmar Kühl
char16_t* ToLower(const char16_t* str)
{
  if( NULL == str )
  {
    return NULL;
  }

  int l = strlen16( str );
  char16_t* ldata = new char16_t[ l + 1];
  auto const& ct = std::use_facet<std::ctype<char16_t>>(std::locale());
  for (int i = 0; i < l; ++i )
  {
    ldata[i] = ct.tolower(str[i]);
  }
  ldata[l] = u'\0'; 
  return ldata;
}

然后可以&#34; std :: use_facet(...)&#34;变得更快?

修改1

我根据以下评论进行了一些测试

  • 1000个字符的字符串
  • 运行了1000次测试。
  • 时间是平均的。

结果

  • 11ms - 我的原始代码,(循环内的std :: use_facet)
  • 10ms - 循环外的std :: use_facet
  • 10ms - 循环外的std :: use_facet并使用ldata.reserve(...)
  • 4ms - 仅使用char16_t *,(调用者必须删除)
  • 5ms - 仅使用char16_t *但返回std :: u16string,(该函数管理删除)。
  • 4ms - 一次多个字符

因此char16_t * ToLower(const char16_t * str){...}函数看起来像一个胜利。 还有其他建议吗?

1 个答案:

答案 0 :(得分:4)

对于初学者来说,你应该在循环之外得到一个方面。这可能会产生巨大的差异,特别是对于locales库的不那么好的实现:

auto const& ct = std::use_facet<std::ctype<char16_t>>(std::locale());
for (std::u16string::const_iterator it = data.begin(); it != data.end(); ++it)
{
    ldata.push_back( ct.tolower(*it) );
}

成员tolower()也有一个重载,它会转换一个对象数组并只调用一次基础virtual函数。也就是说,您可能希望将其用作

std::u16string ToLower(const char16_t* str)
{
    if (!str) {
        return std::u16string();
    }
    std::u16string data(str);
    std::use_facet<std::ctype<char16_t>>(std::locale()).tolower(&data[0], &data[0] + data.size());
    return data;
}