I am reading C++ Primer, 5th Edition. When talking about flushing streams it says:
An output stream might be tied to another stream. In this case, the buffer of the tied stream is flushed whenever the tied stream is read or written. By default, cin and cerr are both tied to cout. Hence, reading cin or writing to cerr flushes the buffer in cout.
I tried to understand this point with an example:
int main() {
std::ofstream out("data.txt");
std::ifstream in("data.txt");
//in.tie(&out);// commenting this will print nothing
out << "Hello there!";
std::string str;
while (in >> str)
std::cout << str << " ";
out.close();
in.close();
}
As you can see above the input and output file stream objects in
and out
use the same file so the output one opens the file "data.txt" and writes some line into it BUT doesn't save it and the input stream tries to read the content of this un-saved file.
If I tie the input stream object in
to out
then I get the content correctly. Does this mean in
forces out
to be flushed?
If I comment out the line in.tie(&out)
then I don't get the content using in?
Please explain to me how it works here. Thank you in advance.
The thing about buffered I/O is that you can never really be sure when the content of the buffer will be flushed to the external sequence. The size of the internal buffer of iostream objects is implementation-defined, and they can decide to flush the buffer (or not flush the buffer) at any point before the stream is closed or destructed. Only when the stream is closed (via an explicit call to close()
or when its lifetime ends) is a stream required to write to the external sequence. This means that an output operation may write to external file right away, or it could wait until there is more content streamed into the buffer.
You can flush a stream explicitly by calling the flush()
method, but when you are flipping between input and output like with std::cin
and std::cout
, it becomes tedious to do std::cout.flush()
before every input operation (if there was a write before it). This is where "tying" streams comes in. When you tie an output stream, the stream that called tie()
(in your case in
, and in general std::cin
) calls flush()
on the tied stream before every I/O operation that it performs. This allows the two streams to remain synchronized.
So to answer your questions directly:
If I tie the input stream object
in
without
then I get the content correctly. Does this meanin
forcesout
to be flushed?
Yes.
If I comment out the line
in.tie(&out)
then I don't get the content usingin
?
It depends on how the buffer is managed by the stream. The stream that performs output could perform a write immediately, or it could wait for its buffer to be filled further before it decides to write, or it could wait until its lifetime ends. This decision varies between iostream implementations.