ofstream close

This is a discussion on ofstream close within the C++ Programming forums, part of the General Programming Boards category; Hi, I wonder if it is required to close an object of ofstream after using it? i.e. similar to FILE ...

  1. #1
    Registered User
    Join Date
    Jan 2009
    Posts
    159

    ofstream close

    Hi,
    I wonder if it is required to close an object of ofstream after using it? i.e. similar to FILE in stdio.h of C?
    I used to do like this:
    Code:
    ofsteam fout(filename);
    fout<<...;
    without fout.close(). Is it right?
    When is it required to call close()? If I try to associate fout with another file, shall I call fout.close() first before call fout.open(newfilename)?
    Thanks and regards!

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    close() will be called when the object is destructed (i.e., when it goes out of scope). You will have to close a file before you can open a new file with the same ofstream object.

    (Edit: Well, I don't know if close itself is actually called during destruction -- but the file is closed at that time.)

  3. #3
    Registered User
    Join Date
    Apr 2006
    Posts
    137
    When using ofstream it is good practice to definitely always stream.close(); after you've finished using it. It's definitely the safer way.
    ★ Inferno provides Programming Tutorials in a variety of languages. Join our Programming Forums. ★

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,317
    Personally, I prefer not to. I'd rather concentrate on limiting the variable to only the scope that it is needed, and letting RAII handle it. On the surface it might seem less clear what is happening (the file is being closed automatically) but if you use RAII enough then it makes much more sense. And since in general the use of RAII is good practice, you could say that limiting scope and not calling close is better practice than always calling close() explicitly.

  5. #5
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I thought you'd call close() only if you indeed for some reason wanted to close the filestream earlier than it goes out of scope.

    Calling it yourself is not definitely this much safer (except perhaps if your program crashes between the point where the filestream could be closed and where it goes out of scope - but then you should fix the program so it doesn't crash, and those points tend to be quite close by anyway).

    Filestreams are an example of RAII which is an important principle in C++: objects should automatically clean up after themselves. This is how you should also design your own classes and it means that you also need to trust that clean-up happens automatically. (You wouldn't also happen to call vector.clear() before it goes out of scope, just to be safe?)
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  6. #6
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,165
    Quote Originally Posted by execute View Post
    When using ofstream it is good practice to definitely always stream.close(); after you've finished using it. It's definitely the safer way.
    It's not good practice and it's not always safer.
    Whether or not to do it is up to the programmer.
    So it's not bad practice, but it isn't exactly "good" practice either.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.
    For information on how to enable C++11 on your compiler, look here.
    よく聞くがいい!私は天才だからね! ^_^

  7. #7
    Registered User
    Join Date
    Apr 2006
    Posts
    137
    Quote Originally Posted by Elysia View Post
    It's not good practice and it's not always safer.
    Whether or not to do it is up to the programmer.
    So it's not bad practice, but it isn't exactly "good" practice either.
    Of course it's good practice. You learn that when you create something new, you learn to delete it. You use malloc you learn to free. It is good practice and it frees up memory faster than letting it go out of scope. Maybe if you're future is in C# or java, then you're right it's bad practice.
    ★ Inferno provides Programming Tutorials in a variety of languages. Join our Programming Forums. ★

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    20,954
    Quote Originally Posted by execute
    Of course it's good practice. You learn that when you create something new, you learn to delete it. You use malloc you learn to free.
    Bad analogy: if you use malloc, you should indeed learn to free. But as in anon's analogy, if you learn to use a std::vector, do you also learn to use the clear() member function even when the container is about to be destroyed by going out of scope?

    The RAII idiom extends on this good practice of learning to release the resources that you allocate by making the release automatic upon the destruction of the associated object. Consequently, it is actually another way to "learn that when you create something new, you learn to delete it", but even better because you cannot forget to do so.

    Quote Originally Posted by execute
    It is good practice and it frees up memory faster than letting it go out of scope.
    That would be true if the object lives in a scope that is larger than necessary. But as Daved pointed out, if it lives in the smallest scope necessary, then it will be destroyed right on time, releasing the resource as it is destroyed.

    Quote Originally Posted by execute
    Maybe if you're future is in C# or java, then you're right it's bad practice.
    Ironically, that is the opposite: since C# and Java lack deterministic destruction, one should explicitly release such resources instead of relying on the garbage collector. (EDIT: But then I recall a discussion here about C# and/or .NET and some form of deterministic destruction, but I am afraid that I am not qualified to comment on such specifics with respect to C#.)
    Last edited by laserlight; 07-13-2009 at 02:22 PM.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,165
    Quote Originally Posted by execute View Post
    Of course it's good practice.
    Of course it's not.

    You learn that when you create something new, you learn to delete it.
    ...Unless you are using a smart pointer.

    You use malloc you learn to free.
    That's C. Not C++.

    It is good practice and it frees up memory faster than letting it go out of scope.
    Clutters up the code with possibly lots of close calls instead of just letting it go out of scope. Furthermore, not using the destructors usually results in bugs because you forgot to add a close call if certain conditions happens.

    Maybe if you're future is in C# or java, then you're right it's bad practice.
    Don't compare C++ to C# and Java.
    C++ has RAII and you can be sure it beats C#, Java AND the manual C way.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.
    For information on how to enable C++11 on your compiler, look here.
    よく聞くがいい!私は天才だからね! ^_^

  10. #10
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,246
    Of course it's good practice. You learn that when you create something new, you learn to delete it.
    So is this how you write your C++ code?
    Code:
    void foo()
    {
        std::auto_ptr<MyClass> ap(new MyClass());
        // use ap
        ap.reset(NULL); // force the destruction of the object in the smart pointer
    }
    Maybe if you're future is in C# or java, then you're right it's bad practice.
    Actually in Java, since there are no destructors you have to explicitly close your file streams.

    EDIT: laserlight and Elysia beat me to it.

  11. #11
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I have sniffed some C# and while destructor calls don't seem to be guaranteed, they have something called a using statement, so if the file object is IDisposable you'd put the file operations in a using block. (It would still be possible to have live references to disposed IDisposables? And it would be possible to forget to use the using block. Which makes me like C++'s destructors.)
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  12. #12
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,158
    Quote Originally Posted by execute View Post
    Of course it's good practice. You learn that when you create something new, you learn to delete it. You use malloc you learn to free. It is good practice and it frees up memory faster than letting it go out of scope. Maybe if you're future is in C# or java, then you're right it's bad practice.
    You are missing the whole point of RAII. Learning to manually match resource allocation with deallocation is learning it "the hard way."

    Designs which require explicit resource deallocation are error prone. Not only because you may forget to release a resource, but because exceptions may cause code paths to exist that you did not anticipate. Proper use of RAII completely eliminates both problems.

    We are trying to take steps forward, not backward.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  13. #13
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Quote Originally Posted by anon View Post
    I have sniffed some C# and while destructor calls don't seem to be guaranteed, they have something called a using statement, so if the file object is IDisposable you'd put the file operations in a using block. (It would still be possible to have live references to disposed IDisposables? And it would be possible to forget to use the using block. Which makes me like C++'s destructors.)
    To elaborate, the using() statement is an exception-safe manual call to close, that looks like this:
    Code:
    using (var v = new SomeClass())
    {
        // code
    }
    and is basically:
    Code:
    var v = new SomeClass();
    try
    {
        // code
    }
    finally
    {
        v.Dispose();
    }
    In my opinion, it is a sad mixing of language and standard library -- the object in the using() must implement the IDisposable interface, so as .Dispose() can be called. Worse, if you have a simple function that just has three objects in it, you're suddly three scopes and tabs deep - generally for a total of 5 * 4 = 20 spaces. (+2 tabs for class & function).
    Furthermore, you have to do this on so many objects, I often wonder if the garbage collection acutally helps. Whereas you might have:
    Code:
    using(Lock a = first_mutex.Lock())
    {
        using(Lock b = second_mutex.Lock())
        {
            using(Lock c = third_mutex.Lock())
            {
                // do something.
            }
        }
    }
    ...which in C++ is:
    Code:
    Lock a = first_mutex.lock();
    Lock b = second_mutex.lock();
    Lock c = third_mutex.lock();
    
    // do something.
    Which is easier to read, write, and maintain? (And, the C++ will likely free up more resources faster, as the C# one still leaves memory allocated until the GC gets it.)

    In short: Don't underestimate the power of RAII. It's an immensely powerful C++ idiom, and when used correctly, it can make quite elegant code. Don't write C code in C++. Write C++, and let RAII take care of you.
    Last edited by Cactus_Hugger; 07-13-2009 at 06:45 PM.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Close an HTTPListenerResponse.OutputStreram
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 04-23-2008, 11:00 PM
  2. open() and close()
    By SoFarAway in forum C Programming
    Replies: 3
    Last Post: 04-08-2005, 01:16 PM
  3. Capturing key presses
    By cgod in forum Windows Programming
    Replies: 6
    Last Post: 11-25-2004, 12:10 PM
  4. Using ofstream in private of a class-errors
    By loobian in forum C++ Programming
    Replies: 3
    Last Post: 12-13-2003, 09:06 PM
  5. Ghost in the CD Drive
    By Natase in forum A Brief History of Cprogramming.com
    Replies: 17
    Last Post: 10-12-2001, 05:38 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21