c++ - 优化文件读取C++

标签 c++ file-io

string str1, str2;
vector<string> vec;

ifstream infile;

infile.open("myfile.txt");
while (! infile.eof() )
{
    getline(infile,str1);
    istringstream is;
        is >> str1;
    while (is >> str2)
    { 
        vec.push_back(str2);
    }
} 

代码所做的是从文件中读取字符串并将其存储到 vector 中。

性能需要优先考虑。我如何优化此代码,以提高读取性能?

最佳答案

正如其他人已经指出的(参见例如 herohuyongtao's answer ),必须修复循环条件以及如何将 str1 放入 istringstream 中。

但是,这里有一个重要的问题,到目前为止每个人都忽略了:您根本不需要 istringstream!

  vec.reserve(the_number_of_words_you_exptect_at_least);

  while (infile >> str1) {

    vec.push_back(str1);
  }

它摆脱了您最初不需要的内部循环,并且不会在每次迭代中创建 istringstream

如果您需要进一步解析每一行并且确实需要 istringstream,请在循环的外部 创建它并通过 istringstream::设置其字符串缓冲区: str(const string& s).

我可以很容易地想象你的循环非常慢:Windows 上的堆分配速度慢得离谱(与 Linux 相比);我被咬过一次。

Andrei Alexandrescu 在他的演讲中(在某种意义上)提出了一个类似的例子 Writing Quick Code in C++, Quickly .令人惊讶的是,在像上面那样的紧密循环中进行不必要的堆分配可能比实际的文件 IO 慢。我很惊讶地看到这一点。


您没有将您的问题标记为 C++11,但这是我在 C++11 中要做的事情。

  while (infile >> str1) {

    vec.emplace_back(std::move(str1));
  }

此操作在 vector 的后面构造字符串,无需复制。我们可以这样做,因为我们不需要将 str1 的内容放入 vector 中。换句话说,不需要将它复制到 vector 后面的一个全新的字符串中,只需将其内容移动到那里就可以了。带有 vec.push_back(str1); 的第一个循环 可能 可能会复制 str1 的内容,这实际上是不必要的。

gcc 4.7.2 中的字符串实现目前是 copy on write ,因此两个循环具有相同的性能;使用哪一个都没有关系。现在。

不幸的是,标准现在禁止写入时复制字符串。我不知道 gcc 开发人员何时会更改实现。如果实现发生变化,无论是移动 (emplace_back(std::move(s))) 还是复制 (push_back(s)) 都可能会影响性能.

如果 C++98 兼容性对您很重要,那么请使用 push_back()。即使将来发生最糟糕的事情并且您的字符串被复制(现在不复制),该拷贝也可以变成 memmove()/memcpy() 这非常快,很可能比从硬盘读取文件内容更快,因此文件 IO 很可能仍然是瓶颈。

关于c++ - 优化文件读取C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21349185/

相关文章:

c++ - 从缓冲区中获取最清晰的 iplimage

c++ - 试图创建一个指向动态分配的 char 数组的指针

c++ - 检查数组是否包含字符

java - 从java文件中获取输入

file-io - Swagger定义,如何指定返回一个文件?

c# - 该进程无法访问该文件,因为它正被另一个进程使用(文件已创建但不包含任何内容)

c++ - http 隧道入门

c++ - 从多个线程收集结果的缓存友好方式

java.io.FileNotFoundException : . svn(访问被拒绝)

java - 写入文件时出现奇怪的字符 (Mac) (Java)