繁体   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