我已经尝试了好几种方法,
std::stringstream m;
m.empty();
m.clear();
这两种方法都行不通。
我已经尝试了好几种方法,
std::stringstream m;
m.empty();
m.clear();
这两种方法都行不通。
当前回答
您可以在一行中清除错误状态并清空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.
最后请注意,在不清除错误状态和所有继承状态的情况下清除流很少有用。这个答案中的一行代码同时做了这两件事。
其他回答
我的观点是:
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";
在gnu c++中,这些函数不会丢弃stringstream中的数据
m.str("");
m.str() = "";
m.str(std::string());
以下为我清空stringstream:
m.str().clear();
您可以在一行中清除错误状态并清空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::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";
}
{
std::stringstream ss;
ss << "the";
}
{
std::stringstream ss;
ss << "heck";
}