Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you clear a stringstream variable?

I've tried several things already,

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

both of which don't work.

like image 265
CodingWithoutComments Avatar asked Aug 21 '08 18:08

CodingWithoutComments


People also ask

How do you clear a Stringstream object?

You can easily clear the content of a StringStream object by using the predefined ss. clear() function. The function will erase the data in the buffer and make the object empty. The below code demonstrates how to clear StringStream in C++.

How do you remove the last character of a Stringstream?

To remove the last character from the string, we will use the seekp() method of the stringstream class. The seekp() method sets the position of the cursor to the place where we want to insert the character. The seekp() method, that we will use, accepts two arguments.

Can you return a Stringstream?

You can't return a stream from a function by value, because that implies you'd have to copy the stream.

Does Stringstream ignore whitespace?

Does stringstream ignoring whitespaces? Technically the operator>>() function ignores leading whitespace. Doing ss. ignore(1) is a way to do it manually, but it's unnecessary.


2 Answers

For all the standard library types the member function empty() is a query, not a command, i.e. it means "are you empty?" not "please throw away your contents".

The clear() member function is inherited from ios and is used to clear the error state of the stream, e.g. if a file stream has the error state set to eofbit (end-of-file), then calling clear() will set the error state back to goodbit (no error).

For clearing the contents of a stringstream, using:

m.str(""); 

is correct, although using:

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

is technically more efficient, because you avoid invoking the std::string constructor that takes const char*. But any compiler these days should be able to generate the same code in both cases - so I would just go with whatever is more readable.

like image 150
Wilka Avatar answered Sep 23 '22 06:09

Wilka


You can clear the error state and empty the stringstream all in one line

std::stringstream().swap(m); // swap m with a default constructed stringstream 

This effectively resets m to a default constructed state, meaning that it actually deletes the buffers allocated by the string stream and resets the error state. Here's an experimental proof:

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

When the demo is compiled with address sanitizer, memory usage is revealed:

================================================================= ==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). 

Pretty steep if you ask me. To hold just 16bytes of payload, we spent 905 bytes ... string streams are no toy. Memory is allocated in two parts:

  • The constructed string stream (392 bytes)
  • The extra buffer needed for the payload (513 bytes). The extraneous size has to do with the allocation strategy chosen by the stream and for payloads <= 8 bytes, blocks inside the initial object can be used.

If you enable method 1 (the one shown in this answer) the extra 513 (payload) bytes are reclaimed, because the stream is actually cleared.

If you enable method2 as suggested in the comments or other answers, you can see that all 905 bytes are in use by the time we exit.

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.

Finally note that it's rarely useful to clear the stream without clearing the error state and all inherited state. The one liner in this answer does both.

like image 32
Nikos Athanasiou Avatar answered Sep 26 '22 06:09

Nikos Athanasiou