22

Below is the code for same case.

#include <iostream>
#include <fstream>

using namespace std;

int main () {
    ofstream myfile;
    myfile.open ("example.txt");
    myfile << "Writing this to a file.\n";
    //myfile.close();
    return 0;
}

What will be the difference if I uncomment the myfile.close() line?

bjb568
  • 11,089
  • 11
  • 50
  • 71
David Mnatsakanyan
  • 455
  • 1
  • 4
  • 15
  • You might find this SO question answers your question also: [Does ofstream close its files automatically?](http://stackoverflow.com/q/12900016/1364007). – Wai Ha Lee Mar 04 '15 at 07:15

4 Answers4

26

There is no difference. The file stream's destructor will close the file.

You can also rely on the constructor to open the file instead of calling open(). Your code can be reduced to this:

#include <fstream>

int main()
{
  std::ofstream myfile("example.txt");
  myfile << "Writing this to a file.\n";
}
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
9

To fortify juanchopanza's answer with some reference from the std::fstream documentation

(destructor)
[virtual](implicitly declared)

destructs the basic_fstream and the associated buffer, closes the file (virtual public member function)

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
6

In this case, nothing will happen and code execution time is very less.

However, if your codes runs for long time when you are continuously opening files and not closing, after a certain time, there may be crash in run time.

when you open a file, the operating system creates an entry to represent that file and store the information about that opened file. So if there are 100 files opened in your OS then there will be 100 entries in OS (somewhere in kernel). These entries are represented by integers like (...100, 101, 102....). This entry number is the file descriptor. So it is just an integer number that uniquely represents an opened file in operating system. If your process open 10 files then your Process table will have 10 entries for file descriptors.

Also, this is why you can run out of file descriptors, if you open lots of files at once. Which will prevent *nix systems from running, since they open descriptors to stuff in /proc all the time.

Similar thing should happen in case of all operating system.

Biplab Kundu
  • 187
  • 1
  • 13
  • It won't prevent the whole system from running, the application will just fail to open more files. – Ruslan Jan 31 '15 at 19:16
  • It might prevent your whole application from running. – user253751 Jan 31 '15 at 19:45
  • Also, note that Windows does not use integers for file descriptors, nor does it call them file descriptors. – user253751 Jan 31 '15 at 19:47
  • 1
    Actually, on UNIX/POSIX compliant OSes, opening 10 files will result in the process FD table containing 13 entries: 10 for the files we opened, and 3 for the standard streams: `stdin`, `stdout` and `stderr`. – ElementW Jan 31 '15 at 20:14
  • This is all correct *except* that the presence or absence of an explicit `close` for this toy program will *not* change its total runtime significantly. The destructor calls `close`, and `close` doesn't do anything if it's already been called, so the difference is on the order of 10 additional machine instructions executed. – zwol Jan 31 '15 at 23:15
  • @immibis `HANDLE` is a typedef for `void *` for backward compatibility only; a `HANDLE` value is *functionally* an integer. (In Win16, if memory serves, HANDLEs were actual pointers into the kernel's data structures, but they were made opaque values in Windows NT, and so everything derived from it.) And, although I can't find what it is right now, I'm sure there is a per-process limit on how many open files you can have. You're right, though, in that they are not *small* integers and values 0, 1, 2 are not special (there are other special values instead). – zwol Jan 31 '15 at 23:25
  • @zwol On Unix, file descriptors are guaranteed to be small integers; on Windows, they are an opaque type (which *might* be an integer, or a pointer, or a ...) – user253751 Jan 31 '15 at 23:51
  • @immibis They are opaque *integers*; it is part of the ABI contract, for instance, that [all kernel `HANDLE`s have a value whose bottom two bits are zero](http://blogs.msdn.com/b/oldnewthing/archive/2005/01/21/358109.aspx). – zwol Feb 01 '15 at 01:26
  • 1
    The destructor closes the file, there's no issue regarding file descriptors. -1 – user541686 Feb 01 '15 at 05:10
  • @Mehrdad, there is no issue *as long as the destructor is called in a timely manner*. If you open a file in `main()` and then enter the program's main loop, it doesn't matter that the file will be automatically closed on program exit: you have effectively leaked a file descriptor. Equally, if your program maintains a list of open files and neglect to clean it up, the destructor won't be called until the file is removed from the list -- until then, the descriptor has effectively been leaked. – Mark Feb 01 '15 at 07:54
  • [File descriptors and file handles are two different abstractions, and many C and C++ implementations for Windows in fact have both, at different layers](http://homepage.ntlworld.com./jonathan.deboynepollard/FGA/redirecting-standard-io.html). The effects of handle or descriptor exhaustion are neither as straightforward or as drastic ("prevent systems from running") as this answer blanket asserts. And the API contract for Win32 is that *opaque means opaque*; one should not be assuming either integer or pointer. – JdeBP Feb 01 '15 at 12:36
1

Under normal conditions there is no difference.

BUT under exceptional conditions (with slight change) the call to close can cause an expception.

int main()
{
    try
    {
        ofstream myfile;
        myfile.exceptions(std::ios::failbit | std::ios::badbit);
        myfile.open("example.txt");

        myfile << "Writing this to a file.\n";


        // If you call close this could potentially cause an exception
        myfile.close();


        // On the other hand. If you let the destructor call the close()
        // method. Then the destructor will catch and discard (eat) the
        // exception.
    }
    catch(...)
    {
        // If you call close(). There is a potential to get here.
        // If you let the destructor call close then the there is
        // no chance of getting here.
    }
}
Martin York
  • 257,169
  • 86
  • 333
  • 562