我正在从ifstream读取随机ascii的文本文件。我需要能够将整个消息放入字符串类型进行字符解析。我当前的解决方案是有效的,但我认为我通过使用相当于这个的等效文件来处理更长的文件的处理时间:
std::string result;
for (std::string line; std::getline(std::cin, line); )
{
result += line;
}
我担心与这样连接字符串相关的开销(这种情况发生了几千次,其中包含10个字符长的消息)。我花了最近几天浏览不同的潜在解决方案,但没有什么是合适的...我不知道提前消息的长度,所以我不认为使用动态大小的字符数组是我的答案
我通读了this SO thread这听起来几乎适用,但仍然让我不确定;
有什么建议吗?
答案 0 :(得分:1)
问题实际上是您提前不知道完整大小,因此无法正确分配内存。我希望你得到的性能与此有关,而不是string
串联的方式,因为它在标准库中有效地完成。
因此,我建议推迟连接,直到您知道最终string
的完整大小。也就是说,首先将所有字符串存储在大vector
中,如下所示:
using namespace std;
vector<string> allLines;
size_t totalSize = 0;
// If you can have access to the total size of the data you want
// to read (size of the input file, ...) then just initialize totalSize
// and use only the second code snippet below.
for (string line; getline(cin, line); )
{
allLines.push_back(line);
totalSize += line.size();
}
然后,您可以提前知道其大小string
:
string finalString;
finalString.reserve(totalSize);
for (vector<string>::iterator itS = allLines.begin(); itS != allLines.end(); ++itS)
{
finalString += *itS;
}
虽然,我应该提一下,如果遇到性能问题,你应该 。不要试图优化不需要的东西,否则你会使你的程序复杂化而没有明显的好处。我们需要优化的地方往往是违反直觉的,因环境而异。只有在您的分析工具告诉您需要时才这样做。
答案 1 :(得分:0)
如果您知道文件大小,请使用结果的成员函数'reserve()'一次。
答案 2 :(得分:0)
我太困了,无法为你整理任何可靠的数据,但最终,如果你不知道大小,那么总是必须做某事喜欢这个。事实上,您的标准库实现足够智能,可以非常巧妙地处理字符串大小调整。 (尽管事实上std::string
没有指数增长保证,std::vector
的方式也是如此。)
因此,虽然您可能会在前五十次左右的迭代中看到不需要的重新分配,但经过一段时间后,重新分配的块变得如此之大,以至于重新分配变得罕见。
如果你发现并发现这仍然是一个瓶颈,也许可以自己使用std::string::reserve
典型的数量。
答案 3 :(得分:0)
您正在为文件中的每一行复制结果数组(当您展开结果时)。而是预先分配结果并以指数方式增长:
std::string result;
result.reserve(1024); // pre-allocate a typical size
for (std::string line; std::getline(std::cin, line); )
{
// every time we run out of space, double the available space
while(result.capacity() < result.length() + line.length())
result.reserve(result.capacity() * 2);
result += line;
}