10

Since c++11, we can move assign one std::fstream object to another, but I'm unable to find documentation that states, what happens if the fstream object is already associated with a file (is_open()==true).

So my question is whether in the following code, File1.txt will properly be closed or if I have to close it manually. And if I have to do it manually, what happens if I don't?

std::fstream file("File1.txt");   
file = std::fstream("File2.txt"); //will this implicitly call file.close()?             
MikeMB
  • 20,029
  • 9
  • 57
  • 102
  • 1
    Ewww. `file = std::fstream("File2.txt");` – erip Feb 01 '16 at 20:27
  • @erip: Is there a typo I'm unable to find or what are you hinting at? – MikeMB Feb 01 '16 at 20:35
  • Just don't look very pretty. – erip Feb 01 '16 at 20:35
  • @erip: Yes, this is of course a contrived example. The actual use case is to first open a file with a temporary `std::fstream` variable and only move assign it to the original variable if it has been opened successfully. – MikeMB Feb 01 '16 at 20:44

2 Answers2

8

Move-assignment of an fstream object will result in move-assignment of its associated filebuf. The documentation for that makes it pretty clear that the old file is closed first (as-if file.rdbuf()->close() not file.close()):

basic_filebuf& operator=(basic_filebuf&& rhs);

  1. Effects: Calls this->close() then move assigns from rhs. After the move assignment *this has the observable state it would have had if it had been move constructed from rhs.
  2. Returns: *this.

basic_fstream& operator=(basic_fstream&& rhs);

  1. Effects: Move assigns the base and members of *this from the base and corresponding members of rhs.
  2. Returns: *this.

(This is the wording from draft n4527, unchanged since at least n3485)

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
4

Since actual file-related machinery is 'hidden' inside corresponding buffers (streams really mostly provide formatting IO), you should be looking at std::basic_filebuf documentation:

First calls close() to close the associated file, then moves the contents of rhs into *this: the put and get buffers, the associated file, the locale, the openmode, the is_open flag, and any other state. After the move, rhs is not associated with a file and rhs.is_open() == false.

Copy from http://en.cppreference.com/w/cpp/io/basic_filebuf/operator%3D

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • Yes, but this talks only about the rhs - it doesn't say, what exactly happens to the state of the lhs right? – MikeMB Feb 01 '16 at 20:28
  • @MikeMB, ' including the buffers, the associated file, the locale, the openmode, the is_open variable' is not good enough for you? – SergeyA Feb 01 '16 at 20:29
  • @SergeyA: Your answer completely avoids talking about what moving the buffer does to the buffer being replaced. – Ben Voigt Feb 01 '16 at 20:31
  • If I have a class with a raw pointer and I just copy everything from the rhs, that doesn't mean, I am deleting what that pointer points to. – MikeMB Feb 01 '16 at 20:31
  • @BenVoigt, my bad. I read the question as being about constructor, not assignment operator. Edited. – SergeyA Feb 01 '16 at 20:34