【问题标题】:Performance. Look for a substring. substr vs find表现。寻找子串。 substr 与查找
【发布时间】:2012-09-12 12:57:09
【问题描述】:

假设我们有一个字符串 var "sA",我想检查字符串 "123" 是否在 sA 的末尾。

什么更好,为什么:

  • if(sA.length() > 2) sA.substr(sA.length()-3) == "123"
  • if(sA.length() > 2) sA.find("123", sA.length() -3) != string::npos

提前致谢

【问题讨论】:

  • 为什么不测试呢?只需对这两种方法计时并进行比较。
  • 绝对不是substr,如果你只想检查,你不需要做一个子字符串。
  • 第二个版本似乎做的比较和字符串复制次数最少...

标签: c++ string performance


【解决方案1】:

第二个代码片段避免了创建两个临时对象(一个用于"123"转换为std::string,另一个用于substr的返回值),所以理论上它应该更快。然而,这种微优化很少有回报:如果随机应用这种优化,使用第二种形式不太可能比第一种形式获得显着收益。

当然,如果你的分析器告诉你你的程序花费了相当大比例的时间来检查字符串的结尾,情况就不同了;在这种情况下,优化可能会有所帮助。

【讨论】:

  • 从经验来看,到目前为止我必须不同意,如果您的大多数应用程序都在做这样的事情,它会产生真正的不同。其中一个进行分配,而另一个不进行分配,通常分配非常昂贵。如果应用程序大部分时间都以这种方式比较子字符串,那么它会产生明显的差异;因此,到目前为止,我同意这可能是一个微优化,在分析器显示有必要之前不应考虑它。
  • @PlasmaHH 感谢您的来信。我澄清了答案,指出如果分析器告诉你,优化是值得的。
【解决方案2】:

如果性能很关键,我认为你不会比这更快(与其他方法相比,不需要分配):

const char needle[] = "abc";
const char *haystack;
const int len = strlen(haystack);

if (len<sizeof(needle))
    return false;
for (int i=0; i<sizeof(needle); i++)
    if (needle[i] != haystack[len-sizeof(needle)+i])
        return false;
return true;

显然可以进行各种微优化,但这种方法是我能想到的最快的。


一个更 C++y 的版本,使用 std::string 作为大海捞针:

const char needle[] = "abc";
const std::string haystack;
const int len = haystack.length();

if (len<sizeof(needle))
    return false;
for (int i=0; i<sizeof(needle); i++)
    if (needle[i] != haystack[len-sizeof(needle)+i])
        return false;
return true;

请注意,只要std::string::operator[] 为 O(1),这两个列表具有相同的性能特征

【讨论】:

  • 如果您必须首先分配 char 数组,这是否仍然更快,因为 OP 表示他假设 C++ 字符串作为起点?
  • OP 似乎仅将 std::string 用于大海捞针。请注意,您可以将const char *haystack 替换为std::string haystack,将const int len = strlen(haystack) 替换为const int len = haystack.length(),并且代码仍然是具有相同性能特征的有效C++(只要std::string::operator[] 在O(1) 中运行)。特别是,不需要分配。
【解决方案3】:

此代码可能比您正在测试的代码更快。 但是只有做一些测试才能知道。

bool EndsWith(const string &strValue, const string &strEnd)
{            
    int iDiference = strValue.size() - strEnd.size();
    if(iDiference >= 0)     
        return (memcmp(strValue.c_str() + iDiference, strEnd.c_str(), strEnd.size()) == 0);

    return false;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    • 2012-05-08
    • 2019-07-20
    • 2019-07-15
    • 1970-01-01
    • 2016-07-27
    相关资源
    最近更新 更多