我已经尝试过几种方法了,
std::stringstream m;
m.empty();
m.clear();
两者都不起作用。
我已经尝试过几种方法了,
std::stringstream m;
m.empty();
m.clear();
两者都不起作用。
empty()
是一个查询而不是一个命令,即它的意思是“你是否为空?”,而不是“请丢弃你的内容”。
clear()
成员函数是从 ios
继承而来,用于清除流的错误状态,例如,如果文件流的错误状态设置为 eofbit
(文件结束),则调用 clear()
将将错误状态设置为 goodbit
(无错误)。stringstream
的内容,请使用:m.str("");
是正确的,尽管使用:
m.str(std::string());
从技术上讲,这种写法更加高效,因为你避免了调用接受const char*
参数的 std::string
构造函数。但现在的任何编译器都应该能够在两种情况下生成相同的代码,所以我建议选择哪种更易读的方式。
你可以一行代码中清除错误状态并清空stringstream
std::stringstream().swap(m); // swap m with a default constructed stringstream
这实际上将m重置为默认构造状态,这意味着它实际上删除了字符串流分配的缓冲区并重置了错误状态。下面是一个实验性的证明:
这将有效地重置m为一个默认构造的状态,这意味着它实际上删除了字符串流分配的缓冲区并重置了错误状态。以下是一个实验性的证明:
int main ()
{
std::string payload(16, 'x');
std::stringstream *ss = new std::stringstream; // Create a memory leak
(*ss) << payload; // Leak more memory
// Now choose a way to "clear" a string stream
//std::stringstream().swap(*ss); // Method 1
//ss->str(std::string()); // Method 2
std::cout << "end" << std::endl;
}
当使用地址检查器编译演示时,会显示内存使用情况:
=================================================================
==10415==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 392 byte(s) in 1 object(s) allocated from:
#0 0x510ae8 in operator new(unsigned long) (/tmp/1637178326.0089633/a.out+0x510ae8)
#1 0x514e80 in main (/tmp/1637178326.0089633/a.out+0x514e80)
#2 0x7f3079ffb82f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291
Indirect leak of 513 byte(s) in 1 object(s) allocated from:
#0 0x510ae8 in operator new(unsigned long) (/tmp/1637178326.0089633/a.out+0x510ae8)
#1 0x7f307b03a25c in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::reserve(unsigned long) (/usr/local/lib64/libstdc++.so.6+0x13725c)
#2 0x603000000010 (<unknown module>)
SUMMARY: AddressSanitizer: 905 byte(s) leaked in 2 allocation(s).
如果你问我,这很陡峭。为了保存仅16个字节的有效负载,我们花费了905个字节……字符串流并不是玩具。内存分配分为两部分:
如果你启用方法1(即此答案中显示的方法),则可回收多余的513(有效负载)字节,因为该流实际上已被清除。
如果您像评论或其他答案中建议的那样启用方法2,则可以看到我们退出时所有905个字节都在使用中。
在程序语义方面,人们可能只关心流“看起来”和“表现”为空,就像vector::clear
会使容量保持不变但将向用户显示空向量一样(当然,向量在这里只需花费16个字节)。考虑到字符串流所需的内存分配,我可以想象这种方法通常会更快。 本答案的主要目标是实际清除字符串流,因为它带来的内存消耗不是闹着玩的。根据您的用例(流的数量,它们保存的数据,清除的频率),您可以选择最佳方法。
最后请注意,很少有用处只清除流而不清除错误状态和所有继承状态。此答案中的一行代码可同时完成两者。
m.str({})
的效率会比调用std::stringstream().swap(m)
更高,正如张的评论所说。简单解释一下:当你调用m.str({})
时,我预计它会重复使用第一个操作期间分配的一些内存来加速下一个操作。而当你调用std::stringstream().swap(m)
时,我希望任何在第一个操作期间分配的内存都会被转移给你刚创建的临时对象,从而失去了那种效率。不过,在实践中进行比较将是有趣的。 - Arthur Tacca无论使用哪个编译器,这应该是最可靠的方法:
m=std::stringstream();
mm.clear(); mm.str("");
起了作用。(如果有 C++11,则使用 swap 更好)。 - hochluse of deleted function ‘std::basic_stringstream<char>& std::basic_stringstream<char>::operator=(const std::basic_stringstream<char>&)
- Rodrigo Gurgelm.str("");
似乎工作正常。
我总是关注它:
{
std::stringstream ss;
ss << "what";
}
{
std::stringstream ss;
ss << "the";
}
{
std::stringstream ss;
ss << "heck";
}
我的看法:
这个方法在xcode和dev-c++中对我有效。我有一个程序是以菜单的形式展示,如果用户按请求反复执行该程序,它将填充一个stringstream变量,该变量在代码第一次运行时工作良好,但下一次用户运行相同的代码时将不会清除stringstream。但是,以下两行代码最终在每次填充字符串变量之前清除了stringstream变量。(尝试了2个小时并进行了谷歌搜索),顺便说一句,仅使用每行代码无法解决问题。
//clear the stringstream variable
sstm.str("");
sstm.clear();
//fill up the streamstream variable
sstm << "crap" << "morecrap";
还有很多其他的答案"可以"工作,但它们经常做不必要的拷贝或重新分配内存。
交换流意味着您需要丢弃其中一个流,浪费内存分配。对于分配默认构造的流也是一样的,
通过stringstream::str
或stringbuf::str
将字符串分配给字符串缓冲区中的字符串可能会丢失已由字符串分配的缓冲区。
清除字符串流的规范方式如下:
void clear(std::stringstream &stream)
{
if (stream.rdbuf()) stream.rdbuf()->pubseekpos(0);
}
std::size_t availSize() (const std::stringstream& stream)
{
if (stream.rdbuf())
return std::size_t(
stream.rdbuf()->pubseekoff(0, std::ios_base::cur, std::ios_base::out));
else
return 0;
}
将数据从流复制到其他预先分配的缓冲区,然后清除它的标准方法是:
std::size_t readAndClear(std::stringstream &stream, void* outBuf, std::size_t outSize)
{
auto const copySize = std::min(availSize(stream), outSize);
if (!copySize) return 0; // takes care of null stream.rdbuf()
stream.rdbuf()->sgetn(outBuf, copySize);
stream.rdbuf()->pubseekpos(0); // clear the buffer
return copySize;
}
我打算让这个答案成为权威的回答。语言专家们,欢迎提供意见。
{
std::stringstream ss;
ss << "what";
}
这是一个概念性问题。
Stringstream 是一个流,因此它的迭代器是向前的,不能返回。在输出 stringstream 中,您需要使用 flush() 来重新初始化它,就像在任何其他输出流中一样。
这些在 GNU C++ 中不会丢弃 stringstream 中的数据
m.str("");
m.str() = "";
m.str(std::string());
以下代码可以清空stringstream:
m.str().clear();