c++中字符串连接的开销
c++ overhead from string concatenation
我正在从ifstream中读取随机ascii文本文件。我需要能够把整个消息变成字符串类型的字符解析。我目前的解决方案是有效的,但是我认为我在更长的文件上浪费了处理时间,因为我使用了如下的等效物:
std::string result;
for (std::string line; std::getline(std::cin, line); )
{
result += line;
}
我担心与这样的串接字符串相关的开销(这种情况发生了几千次,消息有几千个字符长)。我花了几天时间浏览了不同的潜在解决方案,但没有一个是非常合适的……我不知道消息的长度提前,所以我不认为使用一个动态大小的字符数组是我的答案。
我读过这个线程听起来几乎适用,但仍然让我不确定;
有什么建议吗?
真正的问题是您不知道提前的完整大小,所以您不能适当地分配内存。我希望您得到的性能影响与此有关,而不是与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;
}
虽然,我应该提到,如果遇到性能问题,您应该只执行。不要尝试优化不需要的东西,否则会使程序复杂化,而没有明显的好处。我们需要优化的地方往往是违反直觉的,并且可能因环境而异。因此,只有当您的分析工具告诉您需要这样做时,才可以这样做。
如果您知道文件大小,请使用result的成员函数'reserve()'一次
我太困了,不能为你整理任何可靠的数据,但是,最终,在不知道大小的情况下,你总是不得不做这样的事情。事实是,您的标准库实现足够聪明,可以相当聪明地处理字符串大小调整。(尽管std::string
没有指数增长的保证,但std::vector
有。)
因此,尽管您可能会在前50次迭代中看到不必要的重新分配,但过了一段时间,重新分配的块变得如此之大,以至于重新分配变得很少。
如果您进行概要分析并发现这仍然是一个瓶颈,那么您可以自己使用std::string::reserve
并使用典型的数量。
您正在为文件中的每一行复制结果数组(在展开result时)。而是预先分配结果并以指数方式增长:
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;
}
- 实现无开销push_back的最佳方法是什么
- 当套接字连接断开时检测C/C++Unix
- 无法在windows上使用mingw将sqlite3与c连接
- 到连接组件算法的问题(递归)
- QTcpSocket在不阻塞GUI的情况下重新连接到服务器
- 无法在C++中建立与MySQL数据库的连接
- PC中的程序和PHONE中的本机描述应用程序之间的数据连接
- 在Qt Creator中,如何在连接到正在运行的进程后查看控制台输出
- 连接 dockerized 模型和 dockerized 数据库时出现"无法 SQLConnect"错误
- 使用 bfs 解决连接组件问题时得到错误的答案
- 在C++的两个字符串中连接以逗号分隔的唯一值
- 如何修复valgrind启动时的致命错误(与libc6-dbg和libc6-dbg:i386连接)
- C++应用程序 MySQL odbc 数据库连接错误:在引发"otl_tmpl_exception<>"实例后终止调用
- 别名模板的专业化 C++11 中没有开销的最佳替代方案
- OSX蓝牙打开RFCOMMChannelAsync声称已连接,但未建立连接,并且从未调用过委托
- 在 libcurl 连接池中预创建连接
- 套接字连接"Operation not permitted"错误,甚至使用升压/平发器根.cpp
- C++标准是否允许<double>在没有开销的情况下实现 std::可选
- libcurl 和 DNS ttl 中的内部连接管理
- c++中字符串连接的开销