2013-05-29 60 views
3

我正在檢索並存儲可以使用std :: string的字符串的一部分: :擦除或std :: string :: substr。Whis獲取字符串的一部分更快,std :: string :: erase或std :: string :: substr

我想知道下面哪種方法更快(更少的時間完成)和有效的(更少的內存分配/重新分配)。此外,有關如何通過擦除和substr分配/重新分配內存的信息將非常有用。謝謝!

std::string nodeName("ABCD#XYZ#NodeName"); 
const std::string levelSeparator("#"); 

選項1:使用的std :: string :: SUBSTR

std::string::size_type nodeNameStartPosition = nodeName.rfind(levelSeparator); 
if (nodeNameStartPosition != std::string::npos) 
{ 
    nodeNameStartPosition += levelSeparator.length(); 
    nodeName = nodeName.substr(nodeNameStartPosition); 
} 

選項2:使用的std :: string ::擦除

std::string::size_type nodeNameStartPosition = nodeName.rfind(levelSeparator); 
if (nodeNameStartPosition != std::string::npos) 
{ 
    nodeNameStartPosition += levelSeparator.length(); 
    nodeName = nodeName.erase(0, nodeNameStartPosition); 
} 
+5

試試吧。 (填寫) –

+4

這個比較有什麼意義?這兩個做不同的事情。如果你想得到一個子字符串,請執行'substr'。如果你想從一個字符串中刪除,使用'erase'。 –

+0

它可能是基準嗎? – lc2817

回答

2

如果你真的關心,永遠是基準。

你並不需要做一個自我分配ALA nodeName = nodeName.erase(0, nodeNameStartPosition); - 只需使用:

nodeName.erase(0, nodeNameStartPosition); 

這工作,因爲erase已經修改字符串nodeName到位。

任何速度差異絕大部分可能在erase的青睞,因爲肯定沒有內存分配 - 只是在緩衝區內複製。 substr()很可能會創建一個臨時字符串 - 你可以告訴大家,從按值返回類型中的std :: string :: SUBSTR函數原型:

string substr (size_t pos = 0, size_t len = npos) const; 

這由價值迴歸可能需要堆分配,除非短字符串優化開始了。我對優化程序是否可以消除這些開銷表示懷疑。

單獨地,nodeNameStartSeparator明顯是用詞不當,因爲您在級別分隔符的開頭指向它。這一切都歸結爲:

std::string::size_type levelSeparatorPos = nodeName.rfind(levelSeparator); 
if (levelSeparatorPos != std::string::npos) 
    nodeName.erase(0, levelSeparatorPos + levelSeparator.length()); 
1

不給予了充分的背景下,substr版本應該會更快。

原因是:假設您沒有修改原始的nodeName(並且您不顯示nodeName的聲明或初始化)。以上意味着你正在複製一個字符串,初始化它,然後對其進行操作。但是,您可以直接使用substr變體對其進行初始化,而不是進行復制/擦除。

即使它不是本地副本,它仍然會更快,因爲substr對內存的寫入操作更少。它將從開始pos到結束pos返回一個新的字符串,僅對期望的部分執行單個副本(可能是memcpy)。使用擦除示例,您必須複製整個字符串,然後複製需要的所有字符到相應的點。

substr在幾乎所有情況下都應該更快。

編輯:

如果你在一個地方工作的字符串,你需要配置文件,看看差異,它可能實現而有所不同。 如果你是在本地運行的字符串,我期望erase有更好的表現,因爲它不應該需要做的任何撥款,但substr可能永遠會。

0

這是一個基準,其中包括擦除和字符串SUBSTR操作,使用情況是因爲我試圖刪除從字1個字母在單詞字母的每一個有點不同。在這種情況下擦除結果比substr快。

#include <chrono> 
#include <iostream> 
#include <sstream> 

using namespace std; 

static const string STR(1000, 'a'); 

/* 
* remove 1 letter from STR to create a shorter string 
* every letter will be a candidate to remove 
* eg: bcda -> cda, bda, bca, bcd 
* 
* result: 
* 
* stream way takes 63394.1 us 
* append way takes 21007.5 us 
* erase way takes 199.563 us 
* substr way takes 416.735 us 
*/ 

void stream_way() { 
    for (int skip = 0; skip < STR.size(); ++skip) { 
     stringstream ss; 
     for (int i = 0; i < STR.size(); ++i) { 
      if (i != skip) { 
       ss << STR[i]; 
      } 
     } 

     (void) ss.str(); 
    } 
} 

void append_way() { 
    for (int skip = 0; skip < STR.size(); ++skip) { 
     string s; 
     for (int i = 0; i < STR.size(); ++i) { 
      if (i != skip) { 
       s += STR[i]; 
      } 
     } 

     (void) s; 
    } 
} 

void erase_way() { 
    for (int i = 0; i < STR.size(); ++i) { 
     string copy = STR; 
     copy.erase(i, 1); 
     (void) copy; 
    } 
} 

void substr_way() { 
    for (int first_part = 0; first_part < STR.size(); ++first_part) { 
     string s = STR.substr(0, first_part) + STR.substr(first_part + 1, STR.size() - first_part - 1); 
     (void) s; 
    } 
} 

int main() { 
    auto start = chrono::steady_clock::now(); 
    stream_way(); 
    auto end = chrono::steady_clock::now(); 
    chrono::duration<double, micro> diff = end - start; 
    cout << "stream way takes " << diff.count() << " us\n"; 

    start = chrono::steady_clock::now(); 
    append_way(); 
    end = chrono::steady_clock::now(); 
    diff = end - start; 
    cout << "append way takes " << diff.count() << " us\n"; 

    start = chrono::steady_clock::now(); 
    erase_way(); 
    end = chrono::steady_clock::now(); 
    diff = end - start; 
    cout << "erase way takes " << diff.count() << " us\n"; 

    start = chrono::steady_clock::now(); 
    substr_way(); 
    end = chrono::steady_clock::now(); 
    diff = end - start; 
    cout << "substr way takes " << diff.count() << " us\n"; 

    return 0; 
} 
相關問題