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/