簡體   English   中英

C ++更快的方法來添加字符串?

[英]C++ faster way to do string addition?

我發現標准字符串添加速度非常慢所以我正在尋找一些可以加速我的代碼的技巧/黑客。

我的代碼基本結構如下:

inline void add_to_string(string data, string &added_data) {
   if(added_data.length()<1) added_data = added_data + "{";
   added_data = added_data+data;
}

int main()
{
   int some_int = 100;
   float some_float = 100.0;
   string some_string = "test";

   string added_data;
   added_data.reserve(1000*64);

   for(int ii=0;ii<1000;ii++)
   {
      //variables manipulated here
      some_int = ii;  
      some_float += ii;
      some_string.assign(ii%20,'A');
      //then we concatenate the strings!
      stringstream fragment;
      fragment<<some_int <<","<<some_float<<","<<some_string;
      add_to_string(fragment.str(),added_data);
   }
   return;
}

做一些基本的分析,我發現在for循環中使用了大量的時間。 我能做些什么可以大大提高速度嗎? 使用c字符串而不是c ++字符串會有幫助嗎?

字符串添加不是您面臨的問題。 由於它的設計,已知std :: stringstream很慢。 在for循環的每次迭代中,stringstream負責至少2次分配和2次刪除。 這四個操作中的每一個的成本可能比字符串添加的成本更高。

簡要介紹以下內容並衡量差異:

std::string stringBuffer;
for(int ii=0;ii<1000;ii++)
{
  //variables manipulated here
  some_int = ii;  
  some_float += ii;
  some_string.assign(ii%20,'A');
  //then we concatenate the strings!
  char buffer[128];
  sprintf(buffer, "%i,%f,%s",some_int,some_float,some_string.c_str());
  stringBuffer = buffer;
  add_to_string(stringBuffer ,added_data);
}

理想情況下,使用_snprintf或編譯器支持的等效項替換sprintf。

根據經驗,默認情況下使用stringstream進行格式化,並在性能很重要時切換到更快,更不安全的函數,如sprintf,itoa等。

編輯:那,和didierc說的:added_data + = data;

如果不在循環中調用add_to_string ,則可以節省大量字符串操作。

我相信這也是一樣的(盡管我不是C ++專家,並且stringstream知道stringstream作用):

stringstream fragment;
for(int ii=0;ii<1000;ii++)
{
  //variables manipulated here
  some_int = ii;  
  some_float += ii;
  some_string.assign(ii%20,'A');
  //then we concatenate the strings!
   fragment<<some_int<<","<<some_float<<","<<some_string;
}

// inlined add_to_string call without the if-statement ;)
added_data = "{" + fragment.str();

我看到你在added_data上使用了reserve方法,這有助於避免在字符串增長時多次重新分配字符串。

您還應該盡可能使用+= string運算符:

added_data += data;

我認為通過在執行連接時避免在臨時字符串中來回添加added_data副本,上述內容可以節省一些重要時間。

這個+=運算符是string::append方法的一個更簡單的版本,它只是直接在added_data的末尾復制data 由於你做了保留,單獨的操作應該非常快(幾乎相當於一個strcpy)。

但是,當你已經使用stringstream來處理輸入時,為什么要經歷這一切呢? 把它全部放在那里開始!

stringstream類確實效率不高。

如果需要,您可以查看stringstream類以獲取有關如何使用它的更多信息,但是使用字符串作為緩沖區的解決方案似乎可以避免類速度問題。

無論如何,除非你真的知道自己在做什么,否則不要再嘗試重新實現純C中的速度關鍵代碼。 其他一些SO帖子支持這樣做的想法,但我認為最好(閱讀更安全 )盡可能多地依賴標准庫,這將隨着時間的推移而得到增強,並處理你(或我)的許多角落案例)不會想到。 如果您的輸入數據格式是一成不變的,那么您可能會開始考慮采取這種方式,但否則就會過早優化。

如果你用"{"啟動added_data ,你就可以從你的add_to_string方法中刪除if :當字符串為空時, if執行一次,所以你也可以立即將它add_to_string非空。

另外,你的add_to_string會復制data ; 這不是必需的,因為它沒有被修改。 通過const引用接受data應該可以加快速度。

最后,將added_datastring更改為sstream應該允許您在循環中追加它,而不會在循環的每次迭代中創建,復制和丟棄sstream中介。

請查看LLVM中使用的Twine

Twine是一種繩索,它使用二叉樹表示連接的字符串,其中字符串是節點的前序。 由於Twine可以在使用結果時有效地呈現為緩沖區,因此可以避免為中間字符串結果生成臨時值的成本 - 特別是在從不需要Twine結果的情況下。 通過顯式跟蹤葉節點的類型,我們還可以避免為轉換操作創建臨時字符串(例如將整數附加到字符串)。

它可能有助於解決您的問題。

這種方法怎么樣?

這是MSVC 2010報告的DevPartner。

在此輸入圖像描述

string newstring = stringA&stringB;

我不認為字符串很慢,它的轉換可能會使它變慢,也許你的編譯器可能會檢查變量類型是否存在不匹配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM