我已经尝试了好几种方法,
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());
技术上更有效,因为您避免调用std::string构造函数,该构造函数接受const char*。但是现在任何编译器都应该能够在这两种情况下生成相同的代码——所以我只会选择可读性更好的。
在gnu c++中,这些函数不会丢弃stringstream中的数据
m.str("");
m.str() = "";
m.str(std::string());
以下为我清空stringstream:
m.str().clear();
我的观点是:
this seemed to work for me in xcode and dev-c++, I had a program in the form of a menu that if executed iteratively as per the request of a user will fill up a stringstream variable which would work ok the first time the code would run but would not clear the stringstream the next time the user will run the same code. but the two lines of code below finally cleared up the stringstream variable everytime before filling up the string variable. (2 hours of trial and error and google searches), btw, using each line on their own would not do the trick.
//clear the stringstream variable
sstm.str("");
sstm.clear();
//fill up the streamstream variable
sstm << "crap" << "morecrap";
我一直在定义它的范围:
{
std::stringstream ss;
ss << "what";
}
{
std::stringstream ss;
ss << "the";
}
{
std::stringstream ss;
ss << "heck";
}
您可以在一行中清除错误状态并清空stringstream
std::stringstream().swap(m); // swap m with a default constructed stringstream
这有效地将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;
}
Demo
当使用地址杀毒器编译demo时,会显示内存使用情况:
=================================================================
==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字节……字符串流不是玩具。内存分配分为两部分:
构造的字符串流(392字节) 有效负载所需的额外缓冲区(513字节)。多余的大小与流选择的分配策略有关,对于<= 8字节的有效负载,可以使用初始对象中的块。
如果启用方法1(这个答案中显示的方法),额外的513(有效负载)字节将被回收,因为流实际上已被清除。
如果您按照评论或其他答案中建议的那样启用method2,您可以看到在我们退出时,所有905字节都在使用中。
In terms of program semantics, one may only care that the stream "appears" and "behaves" as empty, similar to how a vector::clear may leave the capacity untouched but render the vector empty to the user (of course vector would spend just 16 bytes here). Given the memory allocation that string stream requires, I can imagine this approach being often faster. This answer's primary goal is to actually clear the string stream, given that memory consumption that comes with it is no joke. Depending on your use case (number of streams, data they hold, frequency of clearing) you may choose the best approach.
最后请注意,在不清除错误状态和所有继承状态的情况下清除流很少有用。这个答案中的一行代码同时做了这两件事。
这是一个概念问题。
Stringstream是一个流,所以它的迭代器是向前的,不能返回。在输出stringstream中,需要flush()来重新初始化它,就像在任何其他输出流中一样。
还有许多其他“有效”的答案,但它们通常会进行不必要的复制或重新分配内存。
交换流意味着您需要丢弃其中一个流,从而浪费内存分配。分配一个默认构造的流也是一样, 在字符串缓冲区中为字符串赋值(通过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;
}
我希望这是一个规范的答案。语言律师,欢迎加入。