According to the c++ draft 27.4.2:
The object cin controls input from a stream buffer associated with the object stdin, declared in <cstdio>.
Reading from std::cin is the same as reading from stdin. This means that after fclose(stdin) using std::cin is like calling scanf("%d", &a).
This is exactly what happens in the third case, where fclose(stdin) is called before reading std::cin. In contrast, cases 1-3 the code reads std::cin before fclose(stdin).
Reading from a closed stdin is possibly undefined. Here is what the c11 draft has to say about it:
7.21.7.1 The fgetc function
...
int fgetc(FILE *stream);
...
Returns:
If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-
of-file indicator for the stream is set and the fgetc function returns EOF. Otherwise, the
fgetc function returns the next character from the input stream pointed to by stream.
If a read error occurs, the error indicator for the stream is set and the fgetc function
returns EOF.
This text covers all cases of reading from an open stdin (successful, end-of-file, and a read error), but they don't refer to the case when the stream is closed due to fclose. I could not find anything in the standard that covers this case, which means that the case is undefined.
Conclusion: reading from std::cin after fclose(stdin), without any further freopen is undefined behavior. Trying to read a closed C stream might refer to freed resources.