我已经尝试了好几种方法,

std::stringstream m;
m.empty();
m.clear();

这两种方法都行不通。


当前回答

我一直在定义它的范围:

{
    std::stringstream ss;
    ss << "what";
}

{
    std::stringstream ss;
    ss << "the";
}

{
    std::stringstream ss;
    ss << "heck";
}

其他回答

这应该是最可靠的方式,不管编译器:

m=std::stringstream();

在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.

最后请注意,在不清除错误状态和所有继承状态的情况下清除流很少有用。这个答案中的一行代码同时做了这两件事。

我的观点是:

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";

对于所有标准库类型,成员函数empty()是一个查询,而不是一个命令,也就是说,它的意思是“你是空的吗?”而不是“请扔掉你的内容”。

clear()成员函数继承自ios,用于清除流的错误状态,例如,如果一个文件流的错误状态设置为eofbit(文件结束),那么调用clear()将错误状态设置为goodbit(无错误)。

要清除stringstream的内容,使用:

m.str("");

是正确的,尽管使用:

m.str(std::string());

技术上更有效,因为您避免调用std::string构造函数,该构造函数接受const char*。但是现在任何编译器都应该能够在这两种情况下生成相同的代码——所以我只会选择可读性更好的。