Reputation: 137
I was reading about freopen()
and realized that if we specify stdin/stdout to it, the function will work even if we code using cin/cout.
Researching a little bit, I had found this link freopen() equivalent for c++ streams, where one of the users answered:
From C++ standard 27.3.1:
"The objectcin
controls input from a stream buffer associated with the objectstdin
, declared in<cstdio>
."
So according to the standard, if we redirectstdin
it will also redirectcin
. Vice versa forcout
.
Also saw something similar on CPPReference:
http://en.cppreference.com/w/cpp/io/cin
http://en.cppreference.com/w/cpp/io/cout
The global objects std::cout and std::wcout control output to a stream buffer of implementation-defined type (derived from std::streambuf), associated with the standard C output stream stdout.
That's where it got a little confusing, as I was also reading about flushes and noticed that fflush(stdout) simply won't work with cin/cout.
For example, this sample code won't print anything:
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cout << "Please, enter a number: \n";
fflush(stdout);
cin >> n;
}
While this code below will print to output.txt:
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
freopen("output.txt", "w", stdout);
cout << "Some string";
while (true);
}
Removing ios::sync_with_stdio(false);
from the first sample code, it behaves as expected. And freopen()
works anyway (with or without it).
So the question is: why fflush(stdout) does not work with iostream, while freopen(..., stdout) works? Maybe, this question can get even deeper: to what extension is cin/cout associated with stdin/stdout?
Sorry for the long post. I tried to be as detailed and concise as possible.
I hope it is understandable.
Thanks in advance.
P.S.: I put ios::sync_with_stdio(false);
and cin.tie(0);
on purpose.
Upvotes: 2
Views: 5060
Reputation: 36597
The purpose of the calls ios::sync_with_stdio(false)
and cin.tie(0)
that you have put in "on purpose" is to ensure (1) that C I/O streams (stdout
, etc) are not synchronised with their C++ counterparts (std::cout
, etc) and (2) to ensure that stdout
and stdin
are not tied (i.e. reading from stdin
does not necessarily cause stdout
to be flushed).
That is why fflush(stdout)
does not affect std::cout
in your example. You have specifically disabled such an effect, and the two may be buffered separately.
The effect of freopen()
on any C++ stream that may be synchronised with the supplied file handle is undefined. In practice, there may be some buffers used in common, which explains what you are seeing - at least, with your compiler/library. But that behaviour is not guaranteed with other implementations.
Upvotes: 4
Reputation: 129314
My first question is "why would you want to"? There is a std::ostream::flush()
function for this purpose, so use that e.g. cout.flush();
.
The reason that it "doesn't work" is that the buffer which is flushed with fflush(FILE* f)
is not the same buffer that is used for std::ostream
(or at least it's not guaranteed that it will be). It's quite likely that std::ostream::flush()
does call fflush(FILE*)
on the underlying file object that is part of the implementation.
Upvotes: 5