我想知道
的性能开销是多少string line, word;
while (std::getline(cin, line))
{
istringstream istream(line);
while (istream >> word)
// parse word here
}
我认为这是标记化输入的标准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
}
使用流作为本地堆栈,推送行并弹出单词。 这将摆脱可能的频繁构造函数&amp;在前一个版本中调用析构函数,并利用流内部缓冲效果(这一点是否正确?)。
替代解决方案,可能是将std :: string扩展为支持operator<<
和operator>>
,或者扩展iostream以支持某事。比如locate_new_line
。 只是在这里集思广益。
答案 0 :(得分: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
}
所有这一切,如果测量工具告诉你,性能只是一个问题。 Iostreams具有灵活性和健壮性,filebuf
基本上足够快,因此您可以对代码进行原型设计,使其工作,然后优化瓶颈,而无需重写所有内容。
答案 1 :(得分:1)
在块中定义变量时,它将在堆栈中分配。当您离开区块时,它将从堆栈中弹出。使用此代码,您可以在堆栈上进行大量操作。这也适用于“单词”。您可以使用指针并操作指针而不是变量。指针也存储在堆栈中,但它们指向的位置是堆内存中的一个位置。
此类操作可能会产生开销,用于创建变量,将其推入堆栈并再次从堆栈中弹出。但是使用指针可以分配一次空间,然后使用堆中分配的空间。因为指针可以比真实对象小得多,所以它们的分配会更快。
如您所见getLine()
方法接受line
对象的引用(某种指针),这使得它可以在不再创建字符串对象的情况下使用它。
在您的代码中,line
和word
变量只生成一次,并使用它们的引用。您在每次迭代中唯一的对象是ss
变量。如果您不想在每次迭代中创建它,可以在循环之前进行,并使用其关联方法对其进行初始化。您可以搜索以找到不使用构造函数重新分配它的合适方法。
您可以使用:
string line, word ;
istringstream ss ;
while (std::getline(cin, line))
{
ss.clear() ;
ss.str(line) ;
while (ss >> word) {
// parse word here
}
}
您也可以使用此参考istringstream
编辑:感谢评论@jrok。是的,您应该在分配新字符串之前清除错误标志。这是str()istringstream::str 的参考