通过istringstream进行c ++字符串标记的性能开销

csy*_*hen 4 c++ optimization

我想知道什么是性能开销

string line, word;
while (std::getline(cin, line))
{
    istringstream istream(line);
    while (istream >> word)
        // parse word here
}
Run Code Online (Sandbox Code Playgroud)

我认为这是c++标记输入的标准方法.

再具体一点:

  • 每行是复制三次,先是getline通过istream构造函数,还是通过构造函数,operator>>每个单词的最后一个通道?
  • 经常建设和破坏istream是一个问题吗?如果我istream在外while循环之前定义,那等价的实现是什么?

谢谢!

更新:

一个等效的实现

string line, word;
stringstream stream;
while (std::getline(cin, line))
{
    stream.clear();
    stream << line;
    while (stream >> word)
        // parse word here
}
Run Code Online (Sandbox Code Playgroud)

使用流作为本地堆栈,推送行,并弹出单词.这将摆脱以前版本中可能频繁的构造函数和析构函数调用,并利用流内部缓冲效果(这一点是否正确?).

替代解决方案,可能是扩展std :: string以支持operator<<operator>>/或扩展iostream以支持某些.喜欢locate_new_line.只是在这里集思广益.

Pot*_*ter 6

不幸的是,iostreams不适用于性能密集型工作.问题不在于复制内存中的内容(复制字符串很快),它的虚函数调度,可能是每个字符的几个间接函数调用.

至于你关于复制的问题,是的,因为在你初始化一个新文件时,一切都被复制了stringstream.(字符也会通过getline或从流复制到输出字符串>>,但显然无法阻止.)

使用C++ 11的move工具,您可以消除无关的副本:

string line, word;
while (std::getline(cin, line)) // initialize line
{       // move data from line into istream (so it's no longer in line):
    istringstream istream( std::move( line ) );
    while (istream >> word)
        // parse word here
}
Run Code Online (Sandbox Code Playgroud)

总而言之,如果测量工具告诉您,性能只是一个问题.Iostreams具有灵活性和健壮性,并且filebuf基本上足够快,因此您可以对代码进行原型设计以使其工作,然后优化瓶颈而无需重写所有内容.