Jak cię złapią, to znaczy, że oszukiwałeś. Jak nie, to znaczy, że posłużyłeś się odpowiednią taktyką.
There are two approaches. The more common one is to directly release the memory when you’re done. To understand this, you need a sneak preview of two new keywords in C++: new and delete. As you’ll see in Chapter XX, these do quite a bit, but for now you can think of them as replacements for malloc( ) and free( ) in C. The operator new returns a chunk of memory, and delete frees it. It’s important to know about them here because virtually all memory allocation in C++ is performed with new, and this is also true with ostrstream. If it’s allocated with new, it must be released with delete, so if you have an ostrstream a and you get the char* using str( ), the typical way to clean up the storage isComment
delete []a.str(); This satisfies most needs, but there’s a second, much less common way to release the storage: You can unfreeze the ostrstream. You do this by calling freeze( ), which is a member function of the ostrstream’s streambuf. freeze( ) has a default argument of one, which freezes the stream, but an argument of zero will unfreeze it:Comment a.rdbuf()->freeze(0); Now the storage is deallocated when a goes out of scope and its destructor is called. In addition, you can add more bytes to a. However, this may cause the storage to move, so you better not use any pointer you previously got by calling str( ) – it won’t be reliable after adding more characters.Comment The following example tests the ability to add more characters after a stream has been unfrozen:Comment //: C05:Walrus.cpp // Freezing a strstream //{L} ../TestSuite/Test #include <iostream> #include <strstream> using namespace std; int main() { ostrstream s; s << "'The time has come', the walrus said,"; s << ends; cout << s.str() << endl; // String is frozen // s is frozen; destructor won't delete // the streambuf storage on the heap s.seekp(-1, ios::cur); // Back up before NULL s.rdbuf()->freeze(0); // Unfreeze it // Now destructor releases memory, and // you can add more characters (but you // better not use the previous str() value) s << " 'To speak of many things'" << ends; cout << s.rdbuf(); } ///:~ After putting the first string into s, an ends is added so the string can be printed using the char* produced by str( ). At that point, s is frozen. We want to add more characters to s, but for it to have any effect, the put pointer must be backed up one so the next character is placed on top of the zero inserted by ends. (Otherwise the string would be printed only up to the original zero.) This is accomplished with seekp( ). Then s is unfrozen by fetching the underlying streambuf pointer using rdbuf( ) and calling freeze(0). At this point s is like it was before calling str( ): We can add more characters, and cleanup will occur automatically, with the destructor.Comment It is possible to unfreeze an ostrstream and continue adding characters, but it is not common practice. Normally, if you want to add more characters once you’ve gotten the char* of a ostrstream, you create a new one, pour the old stream into the new one using rdbuf( ) and continue adding new characters to the new ostrstream.Comment Proving movement If you’re still not convinced you should be responsible for the storage of a ostrstream if you call str( ), here’s an example that demonstrates the storage location is moved, therefore the old pointer returned by str( ) is invalid:Comment //: C05:Strmove.cpp // ostrstream memory movement //{L} ../TestSuite/Test #include <iostream> #include <strstream> using namespace std; int main() { ostrstream s; s << "hi"; char* old = s.str(); // Freezes s s.rdbuf()->freeze(0); // Unfreeze for(int i = 0; i < 100; i++) s << "howdy"; // Should force reallocation cout << "old = " << (void*)old << endl; cout << "new = " << (void*)s.str(); // Freezes delete s.str(); // Release storage } ///:~ After inserting a string to s and capturing the char* with str( ), the string is unfrozen and enough new bytes are inserted to virtually assure the memory is reallocated and most likely moved. After printing out the old and new char* values, the storage is explicitly released with delete because the second call to str( ) froze the string again.Comment To print out addresses instead of the strings they point to, you must cast the char* to a void*. The operator << for char* prints out the string it is pointing to, while the operator << for void* prints out the hex representation of the pointer.Comment It’s interesting to note that if you don’t insert a string to s before calling str( ), the result is zero. This means no storage is allocated until the first time you try to insert bytes to the ostrstream.Comment A better way Again, remember that this section was only left in to support legacy code. You should always use string and stringstream rather than character arrays and strstream. The former is much safer and easier to use and will help ensure your projects get finished faster.Comment Output stream formatting The whole goal of this effort, and all these different types of iostreams, is to allow you to easily move and translate bytes from one place to another. It certainly wouldn’t be very useful if you couldn’t do all the formatting with the printf( ) family of functions. In this section, you’ll learn all the output formatting functions that are available for iostreams, so you can get your bytes the way you want them.Comment
|
Wątki
|