簡體   English   中英

C ++存儲矢量 <std::string> 從使用reserve的文件和可能的emplace_back

[英]C++ Storing vector<std::string> from a file using reserve and possibly emplace_back

我正在尋找一種快速的方法來將文件中的字符串存儲到字符串向量中,以便我可以提前保留行數。 做這個的最好方式是什么? 我應該首先控制新行字符還是只獲取文件的總大小,然后保留說大小/ 80,以便粗略估計要保留的內容。 理想情況下,我不希望每次都必須重新分配向量,這會大大減慢大文件的速度。 理想情況下,我會提前計算項目數量,但是我應該通過打開二進制模式計算新行然后重新打開嗎? 這看起來很浪費,對此有些好奇。 還有一種方法可以使用emplace_back來擺脫下面的getline代碼中的臨時somestring。 我確實看到了以下兩個提前計算行數的方法最快的方法來查找文本中的行數(C ++)

std::vector<std::string> vs;
std::string somestring;
std::ifstream somefile("somefilename");
while (std::getline(somefile, somestring))
vs.push_back(somestring);

此外,我可以提前做一些事情以獲得總大小,我可以直接將char *轉換為向量嗎? 這可以追溯到我的保留暗示大小/ 80或一些常數,以預先估計大小的預留大小。

        #include <iostream>   
        #include <fstream>     

        int main () {
          char* contents;
          std::ifstream istr ("test.txt");

          if (istr) 
          {
            std::streambuf * pbuf = istr.rdbuf();

            //which I can use as a reserve hint say size / 80  
            std::streamsize size = pbuf->pubseekoff(0,istr.end);  

            //maybe I can construct the vector from the char buf directly?
            pbuf->pubseekoff(0,istr.beg);       
            contents = new char [size];
            pbuf->sgetn (contents,size);
          }
          return 0;
    }

我不會浪費時間提前計算行數,而是reserve()一個初始值,然后開始推送實際行,如果你碰巧推送了保留的項目數,那么只需reserve()一些空格,然后繼續更多推動,根據需要重復。

std::vector保留空間的策略旨在“按需增長”。 也就是說,你不會一次分配一個字符串,你將首先分配一個,然后,比如說,然后分配一個,依此類推,一百個等等(不完全是那些數字,但這就是想法)。 換句話說,std :: vector :: push_back的實現已經為你管理了這個。

請考慮以下示例:我正在使用兩個版本閱讀戰爭與和平的全文(65007行):一個分配,一個不分配(即一個保留零空間,另一個保留完整的65007行;文本來自: http//www.gutenberg.org/cache/epub/2600/pg2600.txt

#include<iostream>
#include<fstream>
#include<vector>
#include<string>
#include<boost/timer/timer.hpp>

void reader(size_t N=0) {
  std::string line;  
  std::vector<std::string> lines;
  lines.reserve(N);

  std::ifstream fp("wp.txt");  
  while(std::getline(fp, line)) {
    lines.push_back(line);
  }
  std::cout<<"read "<<lines.size()<<" lines"<<std::endl;
}

int main() {
  {
    std::cout<<"no pre-allocation"<<std::endl;
    boost::timer::auto_cpu_timer t;
    reader();
  }
  {
    std::cout<<"full pre-allocation"<<std::endl;    
    boost::timer::auto_cpu_timer t;    
    reader(65007);
  }

  return 0;
}

結果:

no pre-allocation
read 65007 lines
 0.027796s wall, 0.020000s user + 0.000000s system = 0.020000s CPU (72.0%)
full pre-allocation
read 65007 lines
 0.023914s wall, 0.020000s user + 0.010000s system = 0.030000s CPU (125.4%)

你看,對於一個非常微不足道的文本,我有幾毫秒的差異。

你真的需要事先知道線路嗎? 這真的是一個瓶頸嗎? 你是在保存,比如,Wall時間的一秒,但通過預先分配線路使你的代碼復雜化了十倍?

暫無
暫無

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

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